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

后端 未结 10 1948
醉梦人生
醉梦人生 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:33

    Convenience initializers are used when you have some class with a lot of properties that makes it kind of "Painful" to always initialize wit with all that variables, so what you do with convenience initializer is that you just pass some of the variables to initialize the object, and assign the rest with a default value. There is a very good video on Ray Wenderlich website, not sure its free or not because I have a paid account. Here is an example where you can see that instead of initializing my object with all those variables Im just giving it a title.

    struct Scene {
      var minutes = 0
    }
    
    class Movie {
      var title: String
      var author: String
      var date: Int
      var scenes: [Scene]
    
      init(title: String, author: String, date: Int) {
        self.title = title
        self.author = author
        self.date = date
        scenes = [Scene]()
      }
    
      convenience init(title:String) {
        self.init(title:title, author: "Unknown", date:2016)
      }
    
      func addPage(page: Scene) {
        scenes.append(page)
      }
    }
    
    
    var myMovie = Movie(title: "my title") // Using convenicence initializer
    var otherMovie = Movie(title: "My Title", author: "My Author", date: 12) // Using a long normal initializer
    
    0 讨论(0)
  • 2021-01-30 08:33

    the convenience init makes it optional to initialize a class with values.

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

    So it comes in handy when you don't need to specify each and every property for a class. So for instance, if I want to create all adventures with starting HP value of 100, I would use this following convenience init and just add in a name. This is going to cut down on the code a lot.

    class Adventure { 
    
    // Instance Properties
    
        var name: String
        var hp: Int
        let maxHealth: Int = 100
    
        // Optionals
    
        var specialMove: String?
    
        init(name: String, hp: Int) {
    
            self.name = name
            self.hp = hp
        }
    
        convenience init(name: String){
            self.init(name: name, hp: 100)
        }
    }
    
    0 讨论(0)
  • 2021-01-30 08:41

    Standard init:

    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 the superclass chain.

    convenience init:

    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 values. You can also define a convenience initializer to create an instance of that class for a specific use case or input value type.

    per the Swift Documentation

    In a nutshell, this means that you can use a convenience initializer to make calling a designated initializer faster and more "convenient". So convenience initializers require the use of self.init instead of the super.init you might see in an override of a designated initializer.

    pseudocode example:

    init(param1, param2, param3, ... , paramN) {
         // code
    }
    
    // can call this initializer and only enter one parameter,
    // set the rest as defaults
    convenience init(myParamN) {
         self.init(defaultParam1, defaultParam2, defaultParam3, ... , myParamN)
    }
    

    I use these a lot when creating custom views and such that have long initializers with mainly defaults. The docs do a better job explaining than I can, check them out!

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

    All answers are sounds good but, lets understand it with an simple example

    class X{                                     
       var temp1
       init(a: Int){
            self.temp1 = a
           }
    

    Now, we know a class can inherit another class, So

    class Z: X{                                     
       var temp2
       init(a: Int, b: Int){
            self.temp2 = b
            super.init(a: a)
           }
    

    Now, in this case while creating instance for class Z, you will have to provide both values 'a' and 'b'.

    let z = Z(a: 1, b: 2)
    

    But, what if you only want to pass b's value and want rest to take default value for others, then in that case you need to initialise other values a default value. But wait how?, for that U need to set it well before in the class only.

    //This is inside the class Z, so consider it inside class Z's declaration
    convenience init(b: Int){
        self.init(a: 0, b: b)
    }
    convenience init(){
        self.init(a: 0, b: 0)
    }
    

    And now, you can create class Z's instances with providing some, all or none values for the variables.

    let z1 = Z(b: 2)
    let z2 = Z()
    
    0 讨论(0)
  • 2021-01-30 08:50

    It makes sense if your use case is to call an initializer in another initializer in the same class.

    Try to do this in playground

    class Player {
        let name: String
        let level: Int
    
        init(name: String, level: Int) {
            self.name = name
            self.level = level
        }
        
        init(name: String) {
            self.init(name: name, level: 0) //<- Call the initializer above?
    
            //Sorry you can't do that. How about adding a convenience keyword?
        }
    }
    
    Player(name:"LoseALot")
    
    

    With convenience keyword

    class Player {
        let name: String
        let level: Int
    
        init(name: String, level: Int) {
            self.name = name
            self.level = level
        }
        
        //Add the convenience keyword
        convenience init(name: String) {
            self.init(name: name, level: 0) //Yes! I am now allowed to call my fellow initializer!
        }
    }
    
    0 讨论(0)
提交回复
热议问题