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
.