What is the difference between convenience init vs init in swift, explicit examples better

后端 未结 10 1949
醉梦人生
醉梦人生 2021-01-30 08:18

I am having troubles to understand the difference between both, or the purpose of the convenience init.

相关标签:
10条回答
  • 2021-01-30 08:52

    Here is a simply example, taken from the Apple Developer portal.

    Basicly the designated initializer is the init(name: String), it ensure that all stored properties are initialized.

    The init() convenience initializer, taking no argument, automaticly sets the value of name stored property to [Unnamed] by using the designated initializer.

    class Food {
        let name: String
    
        // MARK: - designated initializer
        init(name: String) {
            self.name = name
        }
    
        // MARK: - convenience initializer
        convenience init() {
            self.init(name: "[Unnamed]")
        }
    }
    
    // MARK: - Examples
    let food = Food(name: "Cheese") // name will be "Cheese"
    let food = Food()               // name will be "[Unnamed]"
    

    It is usefull, when you are dealing with large classes, with at least a few stored properties. I would recommend to read some more about optionals and inheritance at the Apple Developer portal.

    0 讨论(0)
  • 2021-01-30 08:52

    A convenience initializer can be defined in a class extension. But a standard one - can not.

    0 讨论(0)
  • 2021-01-30 08:52

    Note: Read The whole Text

    Designated initializers are the primary initializers for a class. A designated initializer fully initializes all properties introduced by that class and calls an appropriate superclass initializer to continue the initialization process up to the superclass chain.

    Convenience initializers are secondary, supporting initializers for a class. You can define a convenience initializer to call a designated initializer from the same class as the convenience initializer with some of the designated initializer’s parameters set to default.

    Designated initializers for classes are written in the same way as simple initializers for value types:

    init(parameters) {
    statements
    }
    

    Convenience initializers are written in the same style, but with the convenience modifier placed before the init keyword, separated by a space:

    convenience init(parameters) {
    statements
    }
    

    A practical Example are as follow:

    class Food {
    var name: String
    init(name: String) {
        self.name = name
    }
    convenience init() {
        self.init(name: "[Unnamed]")
    }
    }
    let namedMeat = Food(name: "Bacon")
    // namedMeat's name is "Bacon”
    

    The init(name: String) initializer from the Food class is provided as a designated initializer because it ensures that all stored properties of a new Food instance are fully initialized. The Food class does not have a superclass, and so the init(name: String) initializer does not need to call super.init() to complete its initialization.

    “The Food class also provides a convenience initializer, init(), with no arguments. The init() initializer provides a default placeholder name for a new food by delegating across to the Food class’s init(name: String) with a name value of [Unnamed]:”

    “let mysteryMeat = Food()
    // mysteryMeat's name is "[Unnamed]”
    

    The second class in the hierarchy is a subclass of Food called RecipeIngredient. The RecipeIngredient class models an ingredient in a cooking recipe. It introduces an Int property called quantity (in addition to the name property it inherits from Food) and defines two initializers for creating RecipeIngredient instances:

    class RecipeIngredient: Food {
    var quantity: Int
    init(name: String, quantity: Int) {
        self.quantity = quantity
        super.init(name: name)
    }
    override convenience init(name: String) {
        self.init(name: name, quantity: 1)
    }
    }
    

    The RecipeIngredient class has a single designated initializer, init(name: String, quantity: Int), which can be used to populate all of the properties of a new RecipeIngredient instance. This initializer starts by assigning the passed quantity argument to the quantity property, which is the only new property introduced by RecipeIngredient. After doing so, the initializer delegates up to the init(name: String) initializer of the Food class.

    page:536 Excerpt From: Apple Inc. “The Swift Programming Language (Swift 4).” iBooks. https://itunes.apple.com/pk/book/the-swift-programming-language-swift-4-0-3/id881256329?mt=11

    0 讨论(0)
  • 2021-01-30 08:53

    Where convenience initializers beat setting default parameter values

    For me, convenience initializers are useful if there is more to do than simply set a default value for a class property.

    Class implementation with designated init()

    Otherwise, I would simply set the default value in the init definition, e.g.:

    class Animal {
    
        var race: String // enum might be better but I am using string for simplicity
        var name: String
        var legCount: Int
    
        init(race: String = "Dog", name: String, legCount: Int = 4) {
            self.race = race
            self.name = name
            self.legCount = legCount // will be 4 by default
        }
    }
    

    Class extension with convenience init()

    However, there might be more to do than simply set a default value, and that is where convenience initializers come in handy:

    extension Animal {
        convenience init(race: String, name: String) {
            var legs: Int
    
            if race == "Dog" {
                legs = 4
            } else if race == "Spider" {
                legs = 8
            } else {
                fatalError("Race \(race) needs to be implemented!!")
            }
    
            // will initialize legCount automatically with correct number of legs if race is implemented
            self.init(race: race, name: name, legCount: legs)
        }
    }
    

    Usage examples

    // default init with all default values used
    let myFirstDog = Animal(name: "Bello")
    
    // convenience init for Spider as race
    let mySpider = Animal(race: "Spider", name: "Itzy")
    
    // default init with all parameters set by user
    let myOctopus = Animal(race: "Octopus", name: "Octocat", legCount: 16)
    
    // convenience init with Fatal error: Race AlienSpecies needs to be implemented!!
    let myFault = Animal(race: "AlienSpecies", name: "HelloEarth")
    
    0 讨论(0)
提交回复
热议问题