2012-06-18 8 views
7

Cuando define un constructor de clase en una clase base (es decir, para establecer una variable de clase estática), ¿es posible anular este constructor de clase en una clase derivada y llamar al constructor desde su padre jerárquico con heredado?¿Puedes anular un constructor de clase y usar heredado?

Ejemplo:

TBaseclass = class(TObject) 
public 
    class constructor ClassCreate; virtual; 
end; 

TOtherClass = class(TBaseClass) 
public 
    class constructor ClassCreate; override; 
end; 

**implementation** 

class constructor TBaseClass.ClassCreate; 
begin 
    //do some baseclass stuff 
end; 

class constructor TotherClass.ClassCreate; 
begin 
    inherited; 
    //do some other stuff 
end; 

Respuesta

16

No hay ninguna razón para class constructors a ser virtual ya que no pueden ser invocados polimórfica. No puedes llamarlos directamente; el compilador les inserta llamadas automáticamente en función de qué clases se usan en un programa. Los métodos virtuales son para el polimorfismo en tiempo de ejecución, pero dado que el compilador sabe exactamente qué constructores de clase está invocando en tiempo de compilación, no hay necesidad de despacho dinámico en constructores de clase o destructores.

No se requieren métodos virtuales para herencia, sin embargo, no debería haber ningún problema al usar inherited en un constructor de clase o destructor de clase. Como señala David's answer, el compilador ignora las llamadas a inherited porque generalmente no es prudente inicializar una clase varias veces, que es lo que haría si realmente lograra llamar al constructor de clases heredado. Si hay algo que necesita suceder dos veces, deberá encontrar una forma diferente de hacerlo realidad.

+1

+1 para "el compilador las inserta automáticamente en función de qué clases se utilizan en un programa". Los constructores de clase principalmente hacen que los enlaces inteligentes sean más eficientes. (porque la inicialización de vars relacionados se vuelve condicional en el uso de la clase) –

+0

No, @Marjan. No fue un voto inexplicable. Fue un voto de alguien que confundió al "constructor de la clase" con el "constructor" y luego se opuso a las afirmaciones de David y yo de que no podían ser virtuales y que no servirían de nada si pudieran. Aquellos con suficiente reputación pueden ver la respuesta de "refutación" que luego fue eliminada porque señalé el malentendido en terminología. Los comentarios que explican los votos ya han sido eliminados. –

+0

Para ser sincero, el verdadero detalle de la respuesta está muy por encima de mi cabeza, simplemente porque nunca tuve que hacer tal cosa. Pero Rob, +1, eres realmente un maestro de la explicación. –

9

Para empezar, ya que constructores de clase no pueden ser virtuales (que no tiene sentido para ellos ser virtual), tiene que quitar los virtual y override palabras clave para que su compilación de código.

Los constructores de clases se suelen utilizar para inicializar los vars de clase. Por lo general, los vars de clase deben inicializarse una vez y solo una vez. Si puede llamar al inherited de la manera que sugiere en la pregunta, entonces se llamaría al TBaseClass.ClassCreate varias veces cuando, de hecho, debe llamarse exactamente una vez.

Si bien puede escribir inherited en un constructor de clase y el código se compilará, el compilador simplemente lo ignorará.

program ClassConstructors; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils; 

var 
    Count: Integer; 

type 
    TBaseclass = class 
    public 
    class constructor ClassCreate; 
    end; 

    TOtherClass = class(TBaseClass) 
    public 
    class constructor ClassCreate; 
    end; 

class constructor TBaseClass.ClassCreate; 
begin 
    inc(Count); 
end; 

class constructor TotherClass.ClassCreate; 
begin 
    inherited; 
end; 

begin 
    TBaseClass.Create.Free; 
    TOtherClass.Create.Free; 
    Writeln(Count);//outputs 1 
    Readln; 
end. 

Tenga en cuenta que, por supuesto, ambos constructores de clase se ejecutan.

+0

¡Gracias por tus comentarios! ¿Pero las llamadas 'heredadas' siempre son ignoradas por el compilador? Pensé que hay apariciones 'heredadas Crear (AOwner)' en algún lugar. ¿Hay llamadas duplicadas? ¿Podrías ayudarme a comentar? – SOUser

+1

@XichenLi 'inherited' se ignora solo cuando no tiene sentido. Por ejemplo, constructores de clase. O en métodos que anulan los métodos abstractos. –

+2

@DavidHeffernan: los métodos abstractos anulados se llaman heredados y producen un EAbstractError si/cuando se hace 'inherited SomeMethodName;' en lugar de 'inherited;' –

Cuestiones relacionadas