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.