Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Aviso del compilador: Method hides virtual method of base type (https://www.clubdelphi.com/foros/showthread.php?t=26851)

dec 05-11-2005 10:34:00

Aviso del compilador: Method hides virtual method of base type
 
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 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. ;)

Código Delphi [-]
 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:


Cita:

Empezado por Ayuda de Delphi
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 de mucho cuidado,... qué os parece...

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

Código Delphi [-]
 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

Código Delphi [-]
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":


Cita:

Empezado por Ayuda de Delphi
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:

Código Delphi [-]
    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

1 Archivos Adjunto(s)
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, 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


La franja horaria es GMT +2. Ahora son las 04:31:22.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi