Почему для построения объекта типа класса "someClass" с значением метатипа используйте "обязательный" инициализатор?
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
- значение anotherClass
, но какой плохой результат будет вызван?
Я знаю, как решить эту проблему, добавив required init() {}
. Но я действительно хочу знать причину второго дела.
Ответы
Ответ 1
Рассмотрим случай, когда мы также имеем подкласс:
class SomeClass {
}
class SomeSubclass : SomeClass {
}
Если вы сохраните тип класса в переменной:
var anotherClass = SomeClass.self
Переменная anotherClass
имеет тип SomeClass.Type
.
Вы можете позже назначить эту переменную подклассу:
anotherClass = SomeSubclass.self
Это верно, поскольку SomeSubclass.Type
- это SomeClass.Type
. На этом этапе anotherClass()
завершится с ошибкой, если инициализатор не будет реализован в подклассе. Это то, что защищает компилятор.
В вашем примере кода это невозможно: вы использовали let
вместо var
поэтому изменение типа невозможно. Может быть, проверки безопасности просто недостаточно нюансированы, чтобы заметить это.