2017-01-11 2 views
7

я создавал свой собственный пользовательский tableViewCell, а затем я получил сообщение об ошибке сказав:В чем разница между требуемым инициализатором и назначенным инициализатором?

«требуется» Initializer 'Init (кодировщик :) должен быть предоставлен подкласс «UITableViewCell»

Я посмотрел на него, и, очевидно, это тоже необходимо реализовать. Но это привело к моей путанице о необходимости против назначенных инициализаторов

Apple Docs говорит:

Обязательного Инициализаторы:

Введите требуемый модификатор перед определением класса инициализатора, чтобы показать, что каждые подкласс класса должен реализовать этот инициализатор:

Назначенные Инициализаторы

Назначенные Инициализаторы являются основными Инициализаторы для класса. A назначенный инициализатор полностью инициализирует все свойства, введенные , этим классом и вызывает соответствующий инициализатор суперкласса для продолжения процесса инициализации цепи суперкласса.

ли следующие утверждения исправить:

  • Необходимый инициализатор всегда обозначается инициализатор
  • Каждый назначенный инициализатор не обязательно обязательные для заполнения Initializer
  • Класс может иметь только один обязательный инициализатору , однако он может иметь несколько назначенных инициализаторов?

Сказав это, я до сих пор не полностью понимаю их функциональные различия.

+0

Я считаю, что у вас может быть требуемый инициализатор удобства, поэтому первое утверждение неверно. – dan

ответ

13

Обязательные инициализаторы и назначенные инициализаторы на самом деле не связаны, хотя соответствующие ключевые слова 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.


Чтобы ответить на ваши заявления:

  • Необходимые инициализаторов не должны быть назначены.
  • Назначенные инициализаторы необязательны.
  • Классы могут иметь несколько требуемых и назначенных инициализаторов.
+0

Спасибо за код-фрагмент, это делает его намного легче понять. Можете ли вы также добавить простой пример для нескольких требуемых инициализаторов? Мне трудно понять их – Honey

+0

Wow. Я родом из «нисходящей» земли и учился ООП самостоятельно 20 лет назад. Все еще программирование протоколов. Это дует мой разум. Up-голосование. – dfd

+0

@Honey: Сделано, фрагменты кода все следуют друг за другом. – Robert