2010-04-29 13 views
5

¿El código del constructor se agrega al código en los constructores de las subclases? ¿O el constructor de la subclase anula la superclase? Teniendo en cuenta este ejemplo constructor de la superclase:¿El código del constructor se agrega al código en los constructores de las subclases?

class Car{ 
    function Car(speed:int){ 
      trace("CAR speed "+speed) 
    } 
} 

... y esta subclase constructor:

class FordCar extends Car{ 
    function FordCar(model:string){ 
      trace("FORD model "+model) 
    } 
} 

Cuando se crea una instancia de FordCar, lo hará esta traza "coche" y "Ford" ??

Editar: ¿Los argumentos también se suman? Ver el código actualizado arriba.

Respuesta

6

Sí. En la mayoría de los lenguajes, se ejecuta el constructor de la clase base y luego el constructor de las subclases. Esto hará que trace: "CAR", luego "FORD".

Ambos constructores de clase siempre deben ejecutarse si construye una instancia de la subclase. Dependiendo del idioma en cuestión, la ejecución real y la elección del constructor de la clase base, incluido el orden, pueden ser diferentes. (Esto es particularmente cierto en los lenguajes que permiten la herencia múltiple - como el orden de ejecución puede ser difícil determinar a primera vista, en algunos casos.)


Editar:

En la mayoría de los idiomas, editadas el código no se compilará La subclase normalmente necesita pasar los argumentos del mismo tipo a los constructores de la clase base. Se trata de un lenguaje específico, pero a menudo se ve algo como:

function FordCar(model: string) : Car(42) { 

En algunos idiomas (principalmente los lenguajes dinámicos), el lenguaje se intenta convertir automáticamente, pero a menudo todavía puede tener que especificar cuál de los constructores de padres a llamar .

A menudo, puede hacerlo:

function FordCar(int: speed, model: string) : Car(speed) { 
    trace("FORD model " + model) 
} 
+0

siempre correré? ¿Sentido? –

+0

@Jeremy: volví a redactar, ¿es mejor? –

+0

¡Sí! Y los argumentos también se suman? Por favor mira mi código actualizado arriba. –

4

Sí, rastreará ambos. Usualmente los constructores de su clase tendrán que llamar al constructor de su clase base. Si se proporciona más de un constructor de clase base, entonces puede tener opciones. Sin embargo, si solo se da uno, entonces DEBE satisfacer sus requisitos.

considere el siguiente código y prestar especial atención a los diversos constructores y cómo funcionan con los constructores de la superclase:

public interface IAnimal 
{ 
    string GetName(); 
    string Talk(); 
} 

public abstract class AnimalBase : IAnimal 
{ 
    private string _name; 

    // Constructor #1 
    protected AnimalBase(string name) 
    { 
     _name = name; 
    } 

    // Constructor #2 
    protected AnimalBase(string name, bool isCutsey) 
    { 
     if (isCutsey) 
     { 
      // Change "Fluffy" into "Fluffy-poo" 
      _name = name + "-poo"; 
     } 
    } 

    // GetName implemention from IAnimal. 
    // In C#, "virtual" means "Let the child class override this if it wants to but is not required to" 
    public virtual string GetName() 
    { 
     return _name; 
    } 

    // Talk "implementation" from IAnimal. 
    // In C#, "abstract" means "require our child classes to override this and provide the implementation". 
    // Since our base class forces child classes to provide the implementation, this takes care of the IAnimal implementation requirement. 
    abstract public string Talk(); 
} 

public class Dog : AnimalBase 
{ 
    // This constructor simply passes on the name parameter to the base class's constructor. 
    public Dog(string name) 
     : base(name) 
    { 
    } 

    // This constructor passes on both parameters to the base class's constructor. 
    public Dog(string name, bool isCutsey) 
     : base(name, isCutsey) 
    { 
    } 

    // Override the base class's Talk() function here, and this satisfy's AnimalBase's requirement to provide this implementation for IAnimal. 
    public override string Talk() 
    { 
     return "Woof! Woof!"; 
    } 
} 

public class SmallDog : Dog 
{ 
    private bool _isPurseDog; 

    // This constructor is unique from all of the other constructors. 
    // Rather than the second boolean representing the "isCutsey" property, it's entirely different. 
    // It's entirely a coincidence that they're the same datatype - this is not important. 
    // Notice that we're saying ALL SmallDogs are cutsey by passing a hardcoded true into the base class's (Dog) second parameter of the constructor. 
    public SmallDog(string name, bool isPurseDog) 
     : base(name, true) 
    { 
     _isPurseDog = isPurseDog; 
    } 

    // This tells us if the dog fits in a purse. 
    public bool DoesThisDogFitInAPurse() 
    { 
     return _isPurseDog; 
    } 

    // Rather than using Dog's Talk() implementation, we're changing this because this special type of dog is different. 
    public override string Talk() 
    { 
     return "Yip! Yip!"; 
    } 
} 

public class Chihuahua : SmallDog 
{ 
    private int _hatSize; 

    // We say that Chihuahua's always fit in a purse. Nothing else different about them, though. 
    public Chihuahua(string name, int hatSize) 
     : base(name, true) 
    { 
     _hatSize = hatSize; 
    } 

    // Of course all chihuahuas wear Mexican hats, so let's make sure we know its hat size! 
    public int GetHatSize() 
    { 
     return _hatSize; 
    } 
} 

public class Cat : AnimalBase 
{ 
    // This constructor simply passes on the name parameter to the base class's constructor. 
    public Cat(string name) 
     : base(name) 
    { 
    } 

    // This constructor passes on both parameters to the base class's constructor. 
    public Cat(string name, bool isCutsey) 
     : base(name, isCutsey) 
    { 
    } 

    // Override the base class's Talk() function here, and this satisfy's AnimalBase's requirement to provide this implementation for IAnimal. 
    public override string Talk() 
    { 
     return "Meoooowwww..."; 
    } 
} 

public class Lion : Cat 
{ 
    public Lion(string name) 
     : base(name) 
    { 
    } 

    // Rather than using Cat's Talk() implementation, we're changing this because this special type of cat is different. 
    public override string Talk() 
    { 
     return "ROAR!!!!!!!!"; 
    } 
} 

[editar]

Su código que agregó por lo general no compilar. El constructor de la subclase generalmente DEBE proporcionar todos los parámetros al constructor de la superclase. No proporcionarlos no es una opción. Vea mi código para ver cómo mis constructores de subclase proporcionan los parámetros a los constructores de superclase. A veces simplemente pasan los parámetros y otras veces ponen realmente códigos true/false valores en.

+0

No, cuando se crea una instancia de la subclase, ¿también ejecutará el código en la superclase? –

+1

Para constructores, sí, ejecutará ambos automáticamente (no tiene una opción aquí). Para los métodos de miembro, la subclase debe hacer referencia específica al método de la superclase. – Jaxidian

1

constructores en C# (y la mayoría de los idiomas) no se heredan y no puede ser anulado.Sin embargo, si el constructor no llama explícitamente a un constructor base, se realiza una llamada implícita al constructor predeterminado de la clase base.

+1

Esto es específico del idioma, pero (en C#) también requiere que la clase base contenga un constructor predeterminado. Si no hay un constructor sin parámetros, obtendrá un error de compilación. –

1

Solo para confirmar que no todos los idiomas son iguales: en Python, el comportamiento predeterminado es la sustitución del constructor de la superclase.

class Car(): 
    def __init__(self, speed): 
    print "speed", speed 
    self.speed = speed 
class FordCar(Car): 
    def __init__(self, model): 
    print "model", model 
    self.speed = 180 
    self.model = model 

>>> FordCar("Mustang") 
model Mustang 

Esto es, imvho, sensible, porque Python permite la herencia múltiple.

Cuestiones relacionadas