【问题标题】:Why must constructing an object of class type 'someClass' with a metatype value use a 'required' initializer?为什么必须使用元类型值构造类类型“someClass”的对象使用“必需”初始化程序?
【发布时间】:2015-08-23 04:21:39
【问题描述】:
class Animal {
    class func generate() -> Animal {
        return self()
    }
}

编译器抱怨使用元类型值构造类类型“Animal”的对象必须使用“必需”初始化程序

我可以理解这一点。如果我这样写一个子类:

class SubAnimal: Animal {
    let head: Int
    init(head: Int) {
        self.head = head
        super.init()
    }
}

它将继承Animal的类方法generate(),但不会继承其默认初始化器init()。所以SmallAnimal.generate() 实际上调用了SmallAnimal(),但是SmallAnimal 没有初始化器init()!当然这是编译器想要阻止的。

让我困惑的是一个类似的问题。

class someClass {

}
let anotherClass = someClass.self
let anotherObject = anotherClass()

编译器仍然抱怨使用元类型值构造类类型“Animal”的对象必须使用“必需”初始化程序

这一次,我无法理解。 anotherClass 是一个元类型值,但是会导致什么不好的结果呢?

我知道如何解决这个问题,添加required init() {} 是解决方案。但是我真的很想知道第二种情况的原因。

【问题讨论】:

    标签: swift


    【解决方案1】:

    考虑我们也有一个子类的情况:

    class SomeClass {
    
    }
    
    class SomeSubclass : SomeClass {
    
    }
    

    如果将类类型存储在变量中:

    var anotherClass = SomeClass.self
    

    变量anotherClass 的类型为SomeClass.Type

    您可以稍后将此变量分配给子类:

    anotherClass = SomeSubclass.self
    

    这是有效的,因为 SomeSubclass.TypeSomeClass.Type。此时,如果未在子类中实现初始化程序,anotherClass() 将失败。这就是编译器要防止的。

    在您的示例代码中,这是不可能的:您使用了let 而不是var,因此更改类型是不可能的。可能是安全检查不够细致,无法注意到这一点。

    【讨论】:

    • 很好的答案。也许let anotherClass: SomeClass.Type = SomeSubClass.self 更简洁?
    • anotherClass 的类型是SomeClass.Type,所以我们使用SomeClass 的初始化器。但它确实是一个SomeSubClass,而SomeSubClass 可能不会继承SomeClass 的初始化器。这就是糟糕的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-31
    相关资源
    最近更新 更多