为什么在Swift类中使用必需的Initializers?

Tal*_*ode 49 initialization swift

我试图理解required在Swift类中使用关键字.

class SomeClass 
{
    required init() {
        // initializer implementation goes here
    }
}
Run Code Online (Sandbox Code Playgroud)

required不会强迫我在我的子类中实现该方法.如果我想覆盖required我的父类的指定初始化程序,我需要写,required而不是override.我知道它是如何工作的但却无法理解为什么我应该这样做.

有什么好处required?据我所知,像C#这样的语言不具备这样的东西,并且工作得很好override.

mat*_*att 81

它实际上只是一种满足编译器的方法,以确保如果这个类有任何子类,它们将继承或实现相同的初始化程序.在这一点上存在疑问,因为规则如果子类具有自己的指定初始化器,则不会继承超类中的初始化器.因此,超类可能有一个初始化程序,而子类可能没有它.required克服了这种可能性.

需要以这种方式满足编译器的一种情况涉及协议,并且工作方式如下:

protocol Flier {
    init()
}
class Bird: Flier {
    init() {} // compile error
}
Run Code Online (Sandbox Code Playgroud)

问题是如果Bird有一个子类,那么该子类必须实现或继承init,并且你没有保证.标记鸟initrequired确实保证.

或者,您可以将Bird标记为final,从而保证反转,即它永远不会有子类.

另一种情况是你有一个工厂方法可以通过调用相同的初始化程序来创建一个类或它的子类:

class Dog {
    var name: String
    init(name: String) {
        self.name = name
    }
}

class NoisyDog: Dog {

}

func dogMakerAndNamer(whattype: Dog.Type) -> Dog {
    let d = whattype.init(name: "Fido") // compile error
    return d
}
Run Code Online (Sandbox Code Playgroud)

dogMakerAndNamerinit(name:)在Dog或Dog子类上调用初始值设定项.但编译器如何确定子类将具有init(name:)初始化器?该required命名平息了编译器的恐惧.

  • 唯一一次你会说 `required` 是在编译器强迫它时。编译器会让您失望,您将使用上述解决方案之一。否则,不要使用它。 (2认同)

Kir*_*nee 7

我想提请注意另一个解决方案Required,除了马特上面给出的.

class superClass{
    var name: String
    required init(){
        // initializer implementation goes here
        self.name = "Untitled"
    }
}
class subClass: superClass {
    var neakName: String = "Subclass Untitled"

}
let instanceSubClass = subClass()
instanceSubClass.name        //output: "Untitled"
instanceSubClass.neakName    //output: "Subclass Untitled"
Run Code Online (Sandbox Code Playgroud)

正如您可以在上面的示例中检查的那样,我已经声明required init()superClass,init()默认情况下继承了superClass的初始化程序subClass,因此您可以创建一个subClass实例let instanceSubClass = subClass().

但是,假设您要在subClass上添加一个指定的初始化程序,以将运行时值分配给存储的属性neakName.当然你可以添加它,但这将导致superClass中没有初始化器将继承到subClass,因此如果你要创建一个实例,subClass你将通过它自己的指定初始化器创建如下.

class superClass{
    var name: String
    init(){
        // initializer implementation goes here
        self.name = "Untitled"
    }
}
class subClass: superClass {
    var neakName: String = "Subclass Untitled"
    init(neakName: String) {
        self.neakName = neakName
    }
}
let instanceSubClass = subClass(neakName: "Bobby")
instanceSubClass.name       //output: "Untitled"
instanceSubClass.neakName   //output: "Bobby"
Run Code Online (Sandbox Code Playgroud)

在上面,您将无法subClass通过just 创建实例subClass(),但是如果您希望superClass的每个子类都必须拥有自己的init()初始化器来创建直接实例subClass().只需将required关键字init()放在superClass 之前,它就会强制您添加init()初始化程序subClass- 如下所示.

class superClass{
    var name: String
    required init(){
        // initializer implementation goes here
        self.name = "Untitled"
    }
}
class subClass: superClass {
    var neakName: String = "Subclass Untitled"
    init(neakName: String) {
        self.neakName = neakName
    }
}    // Compiler error <------------ required `init()` must be provided by subClass.
let instanceSubClass = subClass(neakName: "Bobby")
instanceSubClass.name       //output: "Untitled"
instanceSubClass.neakName   //output: "Bobby"  
Run Code Online (Sandbox Code Playgroud)

所以,required在超类的初始化程序之前使用关键字,当你想要所有的子类必须已经实现required initializer了超类时.


pse*_*117 5

根据文档

Write the required modifier before the definition of a class initializer to
indicate that every subclass of the class must implement that initializer
Run Code Online (Sandbox Code Playgroud)

因此,是的,required确实会强制所有子类实现此构造函数。但是,这不是必需的

 if you can satisfy the requirement with an inherited initializer.
Run Code Online (Sandbox Code Playgroud)

因此,如果创建了无法使用父构造函数完全初始化的更复杂的类,则必须实现require构造函数。

文档中的示例(添加了一些内容):

class SomeClass {
    required init() {
        // initializer implementation goes here
    }
}

class SomeSubclass: SomeClass {
    let thisNeedsToBeInitialized: String
    required init() {
        // subclass implementation of the required initializer goes here
        self.thisNeedsToBeInitialized = "default value"
    }
}
Run Code Online (Sandbox Code Playgroud)