delphi generics inheritance

Delphi Tdictionary herencia



generics inheritance (2)

Intento heredar de Tdictionary y de alguna manera se pierde el comparador predeterminado. Esto es lo que hago en esencia:

type TinpVar = class end; TinputVars = class(Tdictionary<string,TinpVar>) end; TLVRvars = class(TinputVars) constructor create; end; constructor TLVRvars.create; begin inherited; end; var LVRvars : TLVRvars; begin LVRvars:=TLVRvars.create;

Con esta construcción obtengo un AV al agregar un par clave / valor a LVRvars. Finalmente, descubrí que esto se puede evitar cambiando el constructor de la clase heredada a

constructor TLVRvars.create; begin inherited create; end;

No entiendo por qué tengo que hacer eso. Aunque mi problema está resuelto, todavía me gustaría saberlo.


El comparador es un objeto que necesita ser creado en sí mismo. Si no tuviera un constructor en su clase descendente, esperaría que se creara el constructor predeterminado porque estaría implícitamente llamando al constructor heredado. Si creas tu propio constructor, siempre deberías llamar la creación heredada (en mi opinión) para permitir que el ancestro haga su trabajo, en este caso, crear un comparador predeterminado.


En tu constructor

inherited;

llama al constructor con una lista de parámetros idéntica a su constructor. Su constructor no tiene parámetros, y por lo tanto, las llamadas inherited no hacen nada en TObject . No solo ha perdido su comparador, sino que a su instancia le faltan el resto de los pasos necesarios en la construcción.

Cuando lo reemplace con

inherited Create;

el compilador en su lugar realiza la resolución normal del método. Busca la lista de antepasados ​​de la clase y llama al primer método que puede. En ese caso esto es:

constructor Create(ACapacity: Integer = 0); overload;

Por lo tanto, su instancia está correctamente creada.

La documentación está aquí: http://docwiki.embarcadero.com/RADStudio/en/Methods#Inherited

Los extractos clave son:

Si heredado va seguido del nombre de un miembro, representa una llamada de método normal

y

Cuando heredado no tiene un identificador posterior, se refiere al método heredado con el mismo nombre que el método que lo contiene o, si el método adjunto es un controlador de mensajes, al controlador de mensajes heredado del mismo mensaje. En este caso, heredado no toma parámetros explícitos, sino que pasa al método heredado los mismos parámetros con los que se llamó al método adjunto. Por ejemplo:

inherited;

Ocurre frecuentemente en la implementación de constructores. Llama al constructor heredado con los mismos parámetros que se pasaron al descendiente.

Es bastante raro no lo es. A primera vista, parece sorprendente que se llamen diferentes métodos. Sin embargo, el punto clave es que la inherited simple conduce a una coincidencia exacta de las listas de parámetros. Y tu método no tiene parámetros.

Por otro lado inherited Create es una llamada de método estándar. En ese último caso, terminas llamando a un método con un parámetro, utilizando el valor predeterminado para ese parámetro. Entonces, aunque parece que estás llamando a un constructor sin parámetros, no lo eres. Usted está pasando un parámetro, la ACapacity , y un valor de 0 .