PDA

Ver la Versión Completa : Aviso del compilador: Method hides virtual method of base type


dec
05-11-2005, 10:34:00
Hola,

Estoy llevando a cabo un componente que pretende servir como sustituto (veremos hasta qué punto) de la clase "TIniFile", de tal forma que pueda usarse como si de tal clase se tratase, con los mismos nombres de métodos y variables, salvo que la "configuración", las "opciones", las secciones, claves y valores, vaya, se guardan en formato XML. El componente se llama ya (porque tiene ya nombre) "TXmlComoIni" y estará incluido en DecComp (http://dec.clubdelphi.com/archivos/html/componentes.html) en breve, si dios no lo remedia. ;)

Paso a comentar el problema, que, en realidad, no sé si es o no un problema propiamente dicho, pero, desde luego, una molestia, un escrúpulo, algo que no dejaría buen sabor de boca a un servidor incluso aunque en realidad no ocurriera nada y así fueran las cosas, como se las voy a contar.

Al grano. El componente "TXmlComoIni" cuenta con dos constructores, o ha de contar con ellos (en buena medida me baso en otros trabajos, y además no me parece mal la implementación de este modo) para que pueda crearse "sin más" (con el primer constructor), y crearse también ya con ciertas propiedades, como pueda ser el archivo XML en que guardar la información que el componente puede manejar.

Aquí la declaración de los constructores, aquí el ClubDelphi. ;)


type
TXmlComoIni = class(TComponent)
private
FRaizXml: string;
FFileName: TFileName;
{...}
public
constructor Create(AOwner: TComponent); overload; override;
{$WARNINGS OFF} { Hides a virtual method on base class }
constructor Create(AOwner: TComponent; const raizXml: string;
const xmlPath: TFileName); overload;
{$WARNINGS ON}

{...}

Como pueden ver ahora encierro el segundo constructor, que además sobrecarga el nombre del primero, entre directivas de compilación que impiden que el problema se muestre, a veces. El problema es el que comento en el comentario del código fuente y Delphi me ofrece soluciones para el mismo:


Method '<element>' hides virtual method of base type '<element>'

You have declared a method which has the same name as a virtual method in the base class. Your new method is not a virtual method; it will hide access to the base's method of the same name.

(Ejemplo aquí)

There are three alternatives to take when solving this warning.

First, you could specify override to make the derived class' procedure also virtual, and thus allowing inherited calls to still reference the original procedure.

Secondly, you could change the name of the procedure as it is declared in the derived class. Both methods are exhibited in this example.

Finally, you could add the reintroduce directive to the procedure declaration to cause the warning to be silenced for that particular method.

Bien. Pueden ver que yo he optado, por el momento, por la tercera alternativa, que ya digo que, aunque de manual, no me parece correcta, o es que soy un tiquismiquis (http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=tiquismiquis&TIPO_HTML=2&FORMATO=ampliado&sourceid=mozilla-search) de mucho cuidado,... qué os parece...

Aquí la implementación de los constructores actualmente, aquí el ClubDelphi:


resourcestring
rsExtXml = '.xml';
rsRaizXml = 'Opciones';

{ TXmlComoIni }

constructor TXmlComoIni.Create(AOwner: TComponent);
begin
inherited;
Create(AOwner, EmptyStr, EmptyStr);
end;

constructor TXmlComoIni.Create(AOwner: TComponent;
const raizXml: string; const xmlPath: TFileName);
begin
if (raizXml<>EmptyStr) then
FRaizXml := raizXml
else
FRaizXml := rsRaizXml;
if (xmlPath<>EmptyStr) then
FFileName := xmlPath
else
FFileName := ChangeFileExt
(ParamStr(0), rsExtXml);
AbrirDocXml;
end;

He probado unas cuantas cosas... la palabra clave "override" en el segundo constructor, luego de "overload", por ejemplo, pero, no funciona: obtengo un simpático "Declaration of '<element>' differs from previous declaration". Yo diría que el problema puede evitarse, o estoy confundido: desde luego en C# una clase puede tener varios constructores, con distintos parámetros e incluso un constructor de clase. ¿Qué opinan?

Muchas gracias a todos de antemano, ¿eh? Que se sepa. :D

Lepe
05-11-2005, 11:08:02
type
TXmlComoIni = class(TComponent)
private
FRaizXml: string;
FFileName: TFileName;
{...}
public
constructor Create(AOwner: TComponent);reintroduce; overload;

constructor Create(AOwner: TComponent; const raizXml: string;
const xmlPath: TFileName); reintroduce;overload;
end;
implementation
resourcestring
rsExtXml = '.xml';
rsRaizXml = 'Opciones';

{ TXmlComoIni }

constructor TXmlComoIni.Create(AOwner: TComponent);
begin
inherited;
FraizXml := emptystr;
Ffilename := emptyStr;

end;

constructor TXmlComoIni.Create(AOwner: TComponent;
const raizXml: string; const xmlPath: TFileName);
begin
// esto no se hacía cuando el usuario llama directamente
// a este constructor:
Inherited Create(AOwner);

if (raizXml<>EmptyStr) then
FRaizXml := raizXml
else
FRaizXml := rsRaizXml;
if (xmlPath<>EmptyStr) then
FFileName := xmlPath
else
FFileName := ChangeFileExt
(ParamStr(0), rsExtXml);
AbrirDocXml;
end;

dec
05-11-2005, 11:25:59
Hola,

Muchas gracias Lepe. Funciona estupendamente. Aquí está la ayuda sobre la directiva (palabra reservada) "reintroduce":



The reintroduce directive suppresses compiler warnings about hiding previously declared virtual methods. For example,

procedure DoSomething; reintroduce; // the ancestor class also has a DoSomething method

Use reintroduce when you want to hide an inherited virtual method with a new one.

Gracias otra vez Lepe. :cool:

dec
05-11-2005, 11:34:42
Hola,

Acaso añadir que habríamos también de usar la directiva (palabra clave) "override", de modo que "la cosa" quedara como sigue:


public
constructor Create(AOwner: TComponent);reintroduce; overload; override;
constructor Create(AOwner: TComponent; const raizXml: string;
const xmlPath: TFileName); reintroduce;overload;

Saquen sus propias conclusiones. :D Gracias de nuevo Lepe. :)

dec
05-11-2005, 13:35:35
Hola de nuevo,

He añadido ya el componente de que se habla en este Hilo en el paquete de componentes (todos muy sencillos) DecComp (http://dec.clubdelphi.com/), de tal modo que quien quiera pueda descargarlo y obtener así este último engendro que he dado en llamar "TXmlComoIni".

Es el caso que me ha parecido oportuno también adjuntarlo por separado aquí, por si alguien quiere echarle un vistazo rápido, probarlo por separado o porque no quiera, en fin, descargar el paquete antes mencionado.

Lo he probado nomás en Delphi 7 y hace uso del componente "TXmlDocument", el cual no está "de serie" en todas las versiones de Delphi. O sea. :D