Обязательные инициализаторы и назначенные инициализаторы на самом деле не связаны, хотя соответствующие ключевые слова required
и convenience
оба используются для указания ограничений на подклассы.
Требуемые инициализаторов
требуется инициализатор делает гарантию того, что вы можете инициализировать тип, или любой из его подтипов, с этим Инициализатором. Если у вас есть инициализатор в протоколе, и вы соответствуете этому протоколу, вы должны использовать required
(если это класс), потому что этот протокол гарантирует, что инициализатор присутствует в этом классе и в любом из его подклассов. Когда вы используете required
на инициализаторе класса, это означает, что все его подклассы также могут быть инициализированы с использованием этого метода. Это означает, что вам также необходимо добавить этот инициализатор в любой из его подклассов.
protocol TestProtocol {
init()
}
class TestClass: TestProtocol {
required init() {
}
}
Здесь required
ключевое слово должно присутствовать, потому что любые подклассы TestClass
должны также обеспечить init()
(потому что они также соответствуют TestProtocol
).
Имея необходимый Инициализатор позволяет инициализировать класс, не зная, что это во время компиляции, что полезно для целого ряда причин:
let classType: TestProtocol.Type = TestClass.self
let object = classType.init()
Если ваш класс соответствовал несколько протоколам, каждому с разный инициализатор, например, каждый из этих инициализаторов также должен быть потребован:
protocol OtherProtocol {
init(thing: Int)
}
class OtherClass: TestClass, OtherProtocol {
let thing: Int
required init() { // Required from superclass/its protocol
self.thing = 0
}
required init(thing: Int) { // Required from new protocol
self.thing = thing
}
}
Обратите внимание, что добавление super.init()
не требуется в этом особом случае, поскольку Swift будет автоматически включать вызов, если он не принимает никаких параметров ,
Во всех приведенных выше примерах инициализаторы обозначены, поскольку они не содержат ключевое слово convenience
.
Даже если у вас не были никаких протоколов, вы все еще можете использовать required
по инициализации типа класса, который не известен во время компиляции:
class BaseClass {
let value: Int
required init(value: Int) {
self.value = value
}
}
class SubClass: BaseClass {
required init(value: Int) { // Required from superclass
super.init(value: value) // Must call desginated initialiser of superclass
}
}
let someBaseClassType: BaseClass.Type = SubClass.self
let someBaseClassInstance = someBaseClassType.init(value: 1)
Назначенных инициализаторы
A , назначенный Инициализатор - это тот, который не является инициализатором удобства (т.е. отмечен convenience
). Назначенный инициализатор должен убедиться, что все свойства класса имеют значение до окончания инициализации (или вызывается супер инициализатор). У инициализаторов удобства только этого требования нет, потому что они сами должны называть назначенный инициализатор.
class OtherSubClass: BaseClass {
convenience required init(value: Int) {
self.init() // Must call designated initialiser of this class
}
init() {
super.init(value: 0) // Must call designated initialiser of superclass
}
}
(Это довольно надуманный пример.)
В моем опыте, удобство инициализаторов редко бывают полезными, и я, как правило, найти проблемы, которые они решают могут быть решены с помощью дополнительных аргументов на определенных инициализаторов вместо этого. Также необходимо учитывать тот факт, что initialisers can't call convenience initialisers on their superclass, поэтому убедитесь, что у вас нет никаких инициализаторов удобства, которые обеспечивают функциональность, которую не имеют назначенные инициализаторы, если вы намерены подклассом вашего класса!
и перечисления Структура не используют required
или convenience
ключевых слов, потому что эти слова оба используются для обозначения правил инициализации для подклассов, которые только class
поддержки анкеты: required
ключевого слова указует на то, что подклассы должны предусматривать, что Инициализатора, и ключевое слово convenience
указывает, что подклассы не могут вызывать этот инициализатор. Несмотря на отсутствие ключевых слов, они все равно должны предоставлять инициализаторы, определенные в любых протоколах, которые они соответствуют, и вы можете написать «удобные» инициализаторы, которые вызывают self.init
, без ключевого слова convenience
.
Чтобы ответить на ваши заявления:
- Необходимые инициализаторов не должны быть назначены.
- Назначенные инициализаторы необязательны.
- Классы могут иметь несколько требуемых и назначенных инициализаторов.
Я считаю, что у вас может быть требуемый инициализатор удобства, поэтому первое утверждение неверно. – dan