the returning paths must isn from designated called before all swift initialization designated-initializer

swift - returning - ¿Cuál es la diferencia entre un inicializador requerido y un inicializador designado?



is swift (1)

Estaba creando mi propia tableViewCell personalizada y luego recibí un error que decía:

''inicializador'' requerido ''init (codificador :)'' debe ser provisto por la subclase de ''UITableViewCell''

Lo busqué y obviamente también es obligatorio implementarlo. Pero esto condujo a mi confusión sobre los inicializadores requeridos vs. designados

Apple Docs dice:

Iniciales requeridos:

Escriba el modificador requerido antes de la definición de un inicializador de clase para indicar que cada subclase de la clase debe implementar ese inicializador:

Inicializadores designados

Los inicializadores designados son los inicializadores principales para una clase. Un inicializador designado inicializa completamente todas las propiedades introducidas por esa clase y llama a un inicializador de superclase apropiado para continuar el proceso de inicialización de la cadena de superclase.

¿Son correctas las siguientes afirmaciones?

  • Un inicializador requerido es siempre un inicializador designado
  • Cada inicializador designado no es necesariamente un inicializador requerido
  • Una clase solo puede tener un inicializador requerido, sin embargo, puede tener varios inicializadores designados.

Habiendo dicho eso, todavía no entiendo completamente sus diferencias funcionales.


Los inicializadores necesarios y los inicializadores designados no están realmente relacionados, aunque las palabras clave asociadas required y la convenience se usan para especificar restricciones en las subclases.

Inicializadores requeridos

Un inicializador requerido garantiza que puede inicializar un tipo, o cualquiera de sus subtipos, con ese inicializador. Si tiene un inicializador en un protocolo y cumple algo con ese protocolo, debe usar required (si es una clase) porque ese protocolo garantiza que el inicializador esté presente en esa clase y en cualquiera de sus subclases. Cuando usa required en un inicializador de una clase, eso indica que todas sus subclases también pueden inicializarse usando ese método. Esto significa que también necesita agregar ese inicializador a cualquiera de sus subclases.

protocol TestProtocol { init() } class TestClass: TestProtocol { required init() { } }

Aquí, la palabra clave required debe estar presente porque cualquier subclase de TestClass también debe proporcionar init() (porque también se ajustan a TestProtocol ).

Tener un inicializador requerido le permite inicializar una clase sin saber qué es en tiempo de compilación, lo cual es útil por una variedad de razones:

let classType: TestProtocol.Type = TestClass.self let object = classType.init()

Si su clase se ajusta a múltiples protocolos, cada uno con un inicializador diferente, por ejemplo, cada uno de esos inicializadores también debe ser requerido:

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 } }

Tenga en cuenta que no es necesario agregar super.init() en este caso especial, ya que Swift incluirá automáticamente la llamada si no toma parámetros.

En todos los ejemplos anteriores, los iniciadores se designan porque no incluyen la palabra clave de convenience .

Incluso si no tenía ningún protocolo, aún puede hacer uso de required inicializando un tipo de clase que no se conoce en tiempo de compilación:

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)

Inicializadores designados

Un inicializador designado es uno que no es un inicializador de conveniencia (es decir, marcado con convenience ). Un inicializador designado debe asegurarse de que todas las propiedades de la clase tengan un valor antes de que finalice el inicializador (o se llame a un superinicializador). Los inicializadores de conveniencia solo no tienen este requisito porque ellos mismos deben llamar a un inicializador designado.

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 } }

(Este es un ejemplo bastante artificial).

En mi experiencia, los inicializadores de conveniencia rara vez son útiles y tiendo a encontrar que los problemas que resuelven pueden resolverse usando argumentos opcionales sobre los inicializadores designados. También es necesario considerar el hecho de que los inicializadores no pueden llamar a los inicializadores de conveniencia en su superclase , así que asegúrese de no tener ningún inicializador de conveniencia que proporcione la funcionalidad que los inicializadores designados no tienen si pretende que su clase sea subclasificada.

Las estructuras y las enumeraciones no usan las palabras clave required o convenience porque estas palabras clave se usan para indicar reglas de inicialización para subclases, que solo admiten class : la palabra clave required indica que las subclases deben proporcionar ese inicializador y la palabra clave convenience indica que las subclases no pueden llama a ese inicializador. A pesar de no tener las palabras clave, aún deben proporcionar los inicializadores definidos en los protocolos a los que se ajusten, y usted puede escribir inicializadores ''convenientes'' que llamen a self.init , simplemente sin la palabra clave de convenience .

Para responder a sus declaraciones:

  • Los inicializadores necesarios no tienen que ser designados.
  • Los inicializadores designados no necesitan ser requeridos.
  • Las clases pueden tener múltiples inicializadores requeridos y designados.