the returning protocol paths must isn from extension designated called before all swift initialization

swift - returning - must call a designated initializer of the superclass



¿Por qué usar Inicializadores requeridos en clases Swift? (4)

De acuerdo con la documentation :

Write the required modifier before the definition of a class initializer to indicate that every subclass of the class must implement that initializer

Entonces, sí, obligatorio obliga a todas las clases secundarias a implementar este constructor. Sin embargo, esto no es necesario

if you can satisfy the requirement with an inherited initializer.

Entonces, si ha creado clases más complejas que no se pueden inicializar completamente con un constructor padre, debe implementar el constructor require.

Ejemplo de documentación (con algunas cosas adicionales):

class SomeClass { required init() { // initializer implementation goes here } } class SomeSubclass: SomeClass { let thisNeedsToBeInitialized: String required init() { // subclass implementation of the required initializer goes here self.thisNeedsToBeInitialized = "default value" } }

Intento entender el uso de la palabra clave required en las clases de Swift.

class SomeClass { required init() { // initializer implementation goes here } }

required no me obliga a implementar el método en mi clase de niños. Si deseo sobrescribir el inicializador designado required de mi clase principal, necesito escribir y no override . Sé cómo funciona, pero no puedo entender por qué debería hacer esto.

¿Cuál es el beneficio de required ? Por lo que puedo decir, los lenguajes como C # no tienen algo como esto y funcionan bien con la override .


En realidad, es solo una forma de satisfacer al compilador para asegurarle que si esta clase tuviera subclases, heredarían o implementarían este mismo inicializador. Hay dudas sobre este punto, debido a la regla de que si una subclase tiene un inicializador designado propio, no se heredan los inicializadores de la superclase . Por lo tanto, es posible que una superclase tenga un inicializador y la subclase no la tenga. required supera esa posibilidad.

Una situación en la que el compilador debe satisfacerse de esta manera implica protocolos, y funciona así:

protocol Flier { init() } class Bird: Flier { init() {} // compile error }

El problema es que si Bird tuviera una subclase, esa subclase tendría que implementar o heredar init , y usted no lo ha garantizado. Marcar el init de Bird como se required lo garantiza.

Alternativamente, puede marcar a Bird como final , garantizando así lo contrario, es decir, que nunca tendrá una subclase.

Otra situación es cuando tienes un método de fábrica que puede crear una clase o su subclase llamando al mismo inicializador:

class Dog { var name: String init(name: String) { self.name = name } } class NoisyDog: Dog { } func dogMakerAndNamer(whattype: Dog.Type) -> Dog { let d = whattype.init(name: "Fido") // compile error return d }

dogMakerAndNamer llama al init(name:) en la subclase Dog o a Dog. Pero, ¿cómo puede el compilador estar seguro de que una subclase tendrá un init(name:) ? La designación required calma los temores del compilador.


Quiero llamar la atención sobre otra solución provista por Required , aparte de la que Matt ha dado arriba.

class superClass{ var name: String required init(){ // initializer implementation goes here self.name = "Untitled" } } class subClass: superClass { var neakName: String = "Subclass Untitled" } let instanceSubClass = subClass() instanceSubClass.name //output: "Untitled" instanceSubClass.neakName //output: "Subclass Untitled"

Como puede comprobar en el ejemplo anterior, he declarado required init() en superClass , el init() de superClass ha heredado de forma predeterminada en subClass , por lo que puede crear una instancia de subClass let instanceSubClass = subClass() .

Pero, supongamos que desea agregar un inicializador designado en subClass para asignar valor de tiempo de ejecución a la propiedad almacenada neakName . Por supuesto, puede agregarlo, pero eso dará como resultado que no se inicialicen los inicializadores de la superclase a la subclase , de modo que si crea una instancia de subClass , creará a través de su propio inicializador designado como se muestra a continuación.

class superClass{ var name: String init(){ // initializer implementation goes here self.name = "Untitled" } } class subClass: superClass { var neakName: String = "Subclass Untitled" init(neakName: String) { self.neakName = neakName } } let instanceSubClass = subClass(neakName: "Bobby") instanceSubClass.name //output: "Untitled" instanceSubClass.neakName //output: "Bobby"

Aquí arriba, no podrá crear una instancia de subClass por solo subClass() , pero si desea que cada subclase de superClass tenga su propio init() para crear instancia directa por subClass() . Simplemente coloque la palabra clave required antes de init() en superClass, lo forzará a agregar el init() en subClass , como se muestra a continuación.

class superClass{ var name: String required init(){ // initializer implementation goes here self.name = "Untitled" } } class subClass: superClass { var neakName: String = "Subclass Untitled" init(neakName: String) { self.neakName = neakName } } // Compiler error <------------ required `init()` must be provided by subClass. let instanceSubClass = subClass(neakName: "Bobby") instanceSubClass.name //output: "Untitled" instanceSubClass.neakName //output: "Bobby"

SO, utilice la palabra clave required antes del inicializador en la superclase, cuando desee que todas las subclases se hayan implementado, se required initializer de la superclase.


Si está intentando agregar su propio inicializador en la subclase, debe seguir ciertas cosas que fueron declaradas en la clase superior. Por lo tanto, asegúrese de que no olvidará implementar ese método requerido. Si olvida que el compilador le dará el error // fatal error, we''ve not included the required init() error // fatal error, we''ve not included the required init() . Otra razón es que crea un conjunto de condiciones que cualquier subclase debe seguir. La subclase está definiendo su propio inicializador.