Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Coloboración Paypal con ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 12-07-2018
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Crear una clase descendiente de TInifile

Hola a todos

Estoy intentando crear una clase descendiente de TIniFile, con la idea de tener una unidad para gestionar la configuración de laS aplicaciones de tal forma que si se le pasa alguna clase descendiente de un TINIFILE, trabaje con esta clase, en caso de no declara nada que trabaje con la clase general de TINIFile.

Este es el código para la unidad de configs.pas
Código Delphi [-]
unit configs;

interface

uses inifiles;

type
  TClassIniFile = class of TInifile;

var
  ClassIniFile: TClassIniFile = nil;
  IniFileName: string = 'c:\tmp\config.ini';


  function config: TIniFile;

implementation

uses Dialogs;

var
  IniFile:TInifile = Nil;

function config: TIniFile;
begin
  if not Assigned(IniFile) then begin
    if not Assigned(ClassIniFile) then begin
      //Si no hay definida una clase especifica se usa la clase generia de INIFILE
      IniFile := TiniFile.Create(IniFileName)
    end
    else begin
      // se usa la clase especifica
      IniFile := ClassIniFile.Create(IniFileName)
    end;
    // esto es solo en pruebas y es para mostrar que clase se esta utilizando
    MessageDlg(IniFile.ClassName, mtWarning, [mbOK], 0);
  end;
  Result := IniFile;
end;

initialization

finalization
  if assigned(IniFile) then
    IniFile.Free;
end.

Y la forma de utilizarlo en cualquier parte del programa:

Código Delphi [-]
uses configs;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  with config do
    WriteString('prueba', 'prueba', '123');
end;

y así es como redefino una nueva clase descendiente de TInifile
Código Delphi [-]
unit MyIniFiles;

interface

uses IniFiles;

type
  TMyIniFile = class(TIniFile)
  private
  public
    constructor Create(const FileName: string); overload;
  end;

implementation

uses dialogs, configs;

{ TMyIniFile }
constructor TMyIniFile.Create(const FileName: string);
begin
   // esto es solo en pruebas y es para mostrar si pasa por aqui
  MessageDlg('TMyIniFile.create', mtInformation, [mbOK], 0);
  inherited Create(FileName);
end;

initialization
  ClassIniFile := TMyIniFile;
end.


Y aquí es donde viene el problema, tal como esta todo esto declarado, el código del constructor de la clase descendiente (TMyIniFile.Create) no se ejecuta al crear la instancia del objeto desde la variable ClassIniFile y pasa directamente a ejecutar el constructor de la clase padre (TiniFile.create).

Por el contrario si en el procedimiento config lo pusiera de esta forma, entonces si que funciona perfectamente:
Código Delphi [-]
function config: TIniFile;
begin
  if not Assigned(IniFile) then begin
    if not Assigned(ClassIniFile) then
      //Si no hay definida una clase especifica se usa la clase generia de INIFILE
      IniFile := TiniFile.Create(IniFileName)
    else if (ClassIniFile = TMyIniFile) then
      // se usa la clase especifica
      IniFile := TMyIniFile.Create(IniFileName)
    else
      // se usa la clase especifica
      IniFile := ClassIniFile.Create(IniFileName);
    // esto es solo en pruebas y es para mostrar que clase se esta utilizando
    MessageDlg(IniFile.ClassName, mtWarning, [mbOK], 0);
  end;

  Result := IniFile;
end;

Pero de esta forma no quiero ponerlo, por que así estaría forzado a tener que añadir siempre en el uses de la unidad configs la unidad que contiene la clase descendiente, pudiendo estar unas veces incluida en el proyecto y otras veces no.

Me explico mas, mi idea es si en una determinada aplicación que utiliza la unidad CONFIGS le agrego la otra unidad con la clase descendiente, entonces esa aplicación usara esa clase descendiente para gestionar como y donde guardar la configuración, pero si en otra aplicación distinta que también usa la misma unidad CONFIGS, no tiene agregada ninguna unidad descendiente de TINIFILE, entonces se pretende que utilice la clase genérica de TINIFILE.

No se si alguien me puede arrojar luz sobre por que no se ejecuta la clase constructora descendiente al llamarla desde la variable que contiene la clase descendiente.

Gracias por vuestro tiempo
y saludos
Responder Con Cita
  #2  
Antiguo 13-07-2018
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.549
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Creo que el problema está en que el create de la clase base:
Código Delphi [-]
  constructor Create(const FileName: string);
Está definido de esta forma. Ni virtual, ni abstract,...


Si añades un método como este a tu clase:
Código Delphi [-]
  TMyIniFile = class(TIniFile)
  private
  public
    constructor Create(const FileName: string); overload;
    procedure WriteString(const Section, Ident, Value: String); override;
  end;


Comprobará que realmente el objeto es de la clase correcta, porque al ejecutar este código:


Código Delphi [-]
   with config do
    WriteString('prueba', 'prueba', '123');


Realmente ejecuta el método:


Código Delphi [-]
  procedure TMyIniFile.WriteString(const Section, Ident, Value: String);
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #3  
Antiguo 13-07-2018
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Hola Neftali, gracias por responder!!

Si después de unas cuantas pruebas llegue a esa misma conclusión, el problema se encuentra en esta definición class of TInifile que es la que determina el orden de búsqueda, y es que al no poder hacer override sobre el constructor por que la clase padre no lo permite, si el compilador se encuentra con varias clases constructoras declaradas de forma idéntica, entonces la búsqueda de procesos la realiza internamente a algo parecido a una lista con esta forma:

Código:
1:TINIFile{ constructor Create(const FileName: string); }  
2: Resto de clases ascendentes a TINIFile
...
N:TMyIniFile { constructor Create(const FileName: string); }
así que el compilador simplemente coge el primer método que encuentra en la lista que sea del tipo que busca, en este caso el definido para TINIFile.

Y lo solucione creando una clase intermedia (TAvIniFile) donde se define el constructor de forma virtual para así poder sobre-escribirlo en las clases descendientes,

Código Delphi [-]

interface
type
  TAvIniFile = class(TIniFile)
  public
    // se marca el constructor como virtual para poder sobre-escribirlo mas adelante
    constructor Create(const FileName: string); overload; virtual; 
  end;

  TMyIniFile = class(TAvIniFile )
  private
  public
    constructor Create(const FileName: string); override; // ya si se puede usar el override
  end;

  TClassIniFile = class of TAvIniFile;

implementation

constructor TAvIniFile.Create(const FileName: string);
begin
  inherited;
  // aqui no es necesario insertar nada mas, solo esta definido para poder hacer override despues
end;

...

y finalmente sustituyo la declaración de classInifile por TclassInifile = class of TAvInifile, de esta forma la lista de búsqueda quedaría así:
Código:
1: clases descendientes a TAvIniFile con el constructor sobre-escrito, aquí se incluye TMyIniFile   
2: TAvIniFile{ constructor Create(const FileName: string); }  
3: TINIFile{ constructor Create(const FileName: string); }  
4: Resto de clases ascendentes a TINIFile
Gracias de nuevo por responder
Un saludo
Responder Con Cita
  #4  
Antiguo 13-07-2018
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.119
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola a todos,

Ha estado bien visto esto último, bucanero. Yo, en mi ignorancia, iba a responder de entrada que el método constructor de tu clase INI tenía que ser "override" y no "overload". Pero, al probarlo aquí, me dí cuenta de que no era tan sencillo como hacer esto... no alcancé yo hasta donde llegó el compañero Neftalí, que fue descubrir que el constructor de la clase TIniFile no puede sobrescribirse. Vamos, ni alcabcé yo donde el Neftalí llegó, ni por supuesto se me ocurrió pensar en hacer lo que tú al final has hecho. Está bien saberlo.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #5  
Antiguo 13-07-2018
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.549
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por dec Ver Mensaje
Yo, en mi ignorancia, iba a responder de entrada que el método constructor de tu clase INI tenía que ser "override" y no "overload". Pero, al probarlo aquí, me dí cuenta de que no era tan sencillo como hacer esto...

Si, yo también me di cuenta del cambio de palabra overload/override David, pero el problema está en la definición de las clases base, que como he dicho no están definidas para que se puedan "sobreescribir".
Como bien dices, al realizar el cambio da el error de "Cannot override a non-virtual method".
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #6  
Antiguo 13-07-2018
Avatar de movorack
[movorack] movorack is offline
Miguel A. Valero
 
Registrado: feb 2007
Ubicación: Bogotá - Colombia
Posts: 1.346
Poder: 20
movorack Va camino a la famamovorack Va camino a la fama
Puedes usar reintroduce

Código Delphi [-]
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IniFiles;

type
  TMyIniFile = class(TIniFile)
  private
  public
    constructor Create(const FileName: string); reintroduce;
  end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    FConfig: TMyIniFile;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyIniFile }

constructor TMyIniFile.Create(const FileName: string);
begin
  inherited Create(FileName);

   // esto es solo en pruebas y es para mostrar si pasa por aqui
  MessageDlg('TMyIniFile.create', mtInformation, [mbOK], 0);  
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FConfig := TMyIniFile.Create(ChangeFileExt(ParamStr(0), '.ini'));
end;

end.



__________________
Buena caza y buen remar... http://mivaler.blogspot.com
Responder Con Cita
  #7  
Antiguo 13-07-2018
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Gracias DEC y movorack por responder

Cita:
Empezado por Neftali [Germán.Estévez] Ver Mensaje
Si, yo también me di cuenta del cambio de palabra overload/override David, pero el problema está en la definición de las clases base, que como he dicho no están definidas para que se puedan "sobreescribir".
Como bien dices, al realizar el cambio da el error de "Cannot override a non-virtual method".
Ese es el error que me estuvo trastocando todo el tiempo y la necesidad de buscar alguna alternativa al problema.


En cuanto al reintroduce también lo intente y el resultado fue el mismo. En tu código te ha funcionado porque has llamado directamente al método create de la clase TMyIniFile, y de este modo incluso con el overload funciona
Cita:
Empezado por movorack Ver Mensaje
Puedes usar reintroduce

Código Delphi [-]
  FConfig := TMyIniFile.Create(ChangeFileExt(ParamStr(0), '.ini'));
pero en mi código la llamada es a traves de una variable que apunta a una clase derivada de TINIFile y no de TMyIniFile, y para este caso el reintroduce también sigue fallando.

Código Delphi [-]
type
  TClassIniFile = class of TInifile;

var
  ClassIniFile: TClassIniFile = nil;
...
  ClassIniFile:=TMyIniFile;
  ClassIniFile.create(IniFileName);



Gracias a todos por dedicarle tiempo a esta cuestión
Un saludo
Responder Con Cita
  #8  
Antiguo 13-07-2018
Avatar de gatosoft
[gatosoft] gatosoft is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Bogotá, Colombia
Posts: 833
Poder: 22
gatosoft Va camino a la fama
hola bucanero.

Sugiero que utilices la RTTI. Para ello debes cambiar tu codigo de la unidad configs asi:

Código Delphi [-]
unit configs;

interface

uses inifiles;

type
  TClassIniFile = class of TInifile;

var
  ClassIniFile: TClassIniFile = nil;
  IniFileName: string = 'c:\tmp\config.ini';
  ClassIniFileName: String = '';

  function config: TIniFile;

implementation

uses Dialogs, SysUtils, ObjectClone, RTTI;

var
  IniFile:TInifile = Nil;

function config: TIniFile;
var
  RttiContext: TRttiContext;
  RttiType: TRttiInstanceType;
Begin
   if Assigned(IniFile) then
     exit(IniFile);

   if ClassIniFileName <> '' then
      begin
      RttiContext:= TRttiContext.Create;
      RttiType := RttiContext.FindType(ClassIniFileName) as TRttiInstanceType;

      IniFile:= RttiType.GetMethod('Create')
                        .Invoke(RttiType.MetaclassType,
                               [IniFileName]).AsObject as TIniFile;

      end
   else
      IniFile := TIniFile.Create(IniFileName);

   Result:= IniFile;
end;


initialization

finalization
  if assigned(IniFile) then
    IniFile.Free;
end.

y tus unidades descendientes, algo asi:

Código Delphi [-]
unit MyIniFiles;

interface

uses IniFiles, uIMyInis;

type
  TMyIniFile = class(TIniFile)
  private
  public
    class procedure mydummy; static;
    constructor Create(const FileName: string);
  end;

implementation

uses dialogs, configs;

{ TMyIniFile }

constructor TMyIniFile.Create(const FileName: string);
begin
 inherited Create(FileName);
 MessageDlg('TMyIniFile2.Crear', mtInformation, [mbOK], 0);
end;

class procedure TMyIniFile.mydummy;
begin

end;

Initialization
  TMyIniFile.mydummy; //Me encontré con este error
  ClassIniFileName:='MyIniFiles.TMyIniFile';
end.
Responder Con Cita
  #9  
Antiguo 13-07-2018
Avatar de gatosoft
[gatosoft] gatosoft is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Bogotá, Colombia
Posts: 833
Poder: 22
gatosoft Va camino a la fama
Igual, amigo bucanero, creo que vas por un lado que no es. Lo que tu quieres implementar, puede salir mejor utilizando interfaces ==> El problema con el caso específico que propones es que las interfaces no admiten constructores....
Responder Con Cita
  #10  
Antiguo 13-07-2018
Avatar de movorack
[movorack] movorack is offline
Miguel A. Valero
 
Registrado: feb 2007
Ubicación: Bogotá - Colombia
Posts: 1.346
Poder: 20
movorack Va camino a la famamovorack Va camino a la fama
Al fin no nos tomaron la foto donde TopX, Tu y yo estábamos revisando este hilo.
__________________
Buena caza y buen remar... http://mivaler.blogspot.com
Responder Con Cita
  #11  
Antiguo 16-07-2018
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Gracias gatosoft por responder

Cita:
Empezado por gatosoft Ver Mensaje
hola bucanero.

Sugiero que utilices la RTTI. Para ello debes cambiar tu codigo de la unidad configs asi:
En cuanto a tu sugerencia de usar la RTTI es por donde en un principio pensé que podría ir la solución a este problema, aunque en estos temas de la RTTI me pierdo...

Viendo tu código me encuentro que en la linea donde debe de buscar y localizar la classe devuelve NIL y no la encuentra.
Cita:
Empezado por gatosoft Ver Mensaje
Código Delphi [-]
      RttiType := RttiContext.FindType(ClassIniFileName) as TRttiInstanceType;
El problema imagino que viene de que para que la pueda localizar hay que registrar previamente la clase.
Código Delphi [-]
  RegisterClass(TMyIniFile);
Pero aquí aparece otro problema, y es que el procedimiento RegisterClass(AClass: TPersistentClass) requiere que la clase a registrar sea descendiente de TPersistentClass, y yo estoy intentando registrar una clase descendiente de TINIFile que a su vez es una una classe descendiente directamente de TObject y por este motivo el compilador da el siguiente error E2010 Incompatible types: 'TPersistentClass' and 'class of TMyIniFile'


Cita:
Empezado por gatosoft Ver Mensaje
Igual, amigo bucanero, creo que vas por un lado que no es. Lo que tu quieres implementar, puede salir mejor utilizando interfaces ==> El problema con el caso específico que propones es que las interfaces no admiten constructores....
En cuanto a esta propuesta... sinceramente, no veo como aplicar una solución...

Porque mi idea final a parte de lo ya explicado es sobre-escribir los métodos de lectura/escritura de mi clase descendiente de TINIFile, para que en vez de guardar los datos en un fichero los guarde directamente en la BBDD, manteniendo la máxima compatibilidad con el componente original para que en determinados casos que no quiera utilizar mi componente propio y/o guardar en la BBDD puede usar directamente un TINIFile.
Responder Con Cita
  #12  
Antiguo 16-07-2018
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Hola Movorack, realmente no se a que te refieres con esto ....
Cita:
Empezado por movorack Ver Mensaje
Al fin no nos tomaron la foto donde TopX, Tu y yo estábamos revisando este hilo.
Responder Con Cita
  #13  
Antiguo 16-07-2018
Avatar de gatosoft
[gatosoft] gatosoft is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Bogotá, Colombia
Posts: 833
Poder: 22
gatosoft Va camino a la fama
Cita:
Empezado por bucanero Ver Mensaje
En cuanto a tu sugerencia de usar la RTTI es por donde en un principio pensé que podría ir la solución a este problema, aunque en estos temas de la RTTI me pierdo...
Viendo tu código me encuentro que en la linea donde debe de buscar y localizar la classe devuelve NIL y no la encuentra.
El problema imagino que viene de que para que la pueda localizar hay que registrar previamente la clase.
Yo también me encontré con ese problema del Nil, y por eso linkeaba la solución en ésta linea de código.

Código Delphi [-]
Initialization
  TMyIniFile.mydummy; //Me encontré con este error


en el hilo se dice:
Cita:

Probably the class has not included by the delphi linker in the final executable. A fast try can be the following:

1.Declare a static method on your class. This method should be an empty method, a simple begin end.
2.Call this static method in the initialization section of this unit.
3. Ensure that the unit is referenced in your project somewhere.
4.Now you should see the class with TRttiContext.FindType

Cita:
Empezado por bucanero Ver Mensaje
En cuanto a esta propuesta... sinceramente, no veo como aplicar una solución...

Porque mi idea final a parte de lo ya explicado es sobre-escribir los métodos de lectura/escritura de mi clase descendiente de TINIFile, para que en vez de guardar los datos en un fichero los guarde directamente en la BBDD, manteniendo la máxima compatibilidad con el componente original para que en determinados casos que no quiera utilizar mi componente propio y/o guardar en la BBDD puede usar directamente un TINIFile.
Bueno, eso es nuevo, creí que querías extender la funcionalidad, y no sobre escribirla.

Existe una técnica que te puede servir y es la de interceptores, pero como todo, no es para abusar de ella.

y funciona mas o menos asi:

En la clausula Uses defines la unidad Inifiles, que contiene la implementación nativa del componente.

Después, defines la clase "interceptora" TIniFile (Tiene el mismo nombre de la nativa) la cual hereda de System.IniFiles.TIniFile (debes especificar la unidad).

Y en esta nueva clase, puedes definir nueva funcionalidad y sobreescribir la existente.


Código Delphi [-]
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IniFiles, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


  TIniFile = Class(System.IniFiles.TIniFile)
  Private
  Public
    procedure WriteString(const Section, Ident, Value: String); reintroduce;
  End;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
Var vIniFile: TIniFile;
begin
  Try
    vIniFile:= TIniFile.Create('C:\MyFile.ini');
    vIniFile.WriteInteger('prueba','numero',5); //este lo escribe
    vIniFile.WriteString('prueba','texto','helou'); //ese lo muestra en un showmessage
  Finally
    vIniFile.Free;
  End;
end;

{ TIniFile }

procedure TIniFile.WriteString(const Section, Ident, Value: String);
begin
  showMessage('Sobre-escribí el metodo '+Value);
end;

end.


en tu caso, modificarias tu codigo aqsí..

Código Delphi [-]
unit MyIniFiles;

interface

uses IniFiles;

type
  TIniFile = class(System.IniFiles.TIniFile)
  private
  public
    class procedure mydummy; static;
    constructor Create(const FileName: string);
  end;

implementation



revisa
Responder Con Cita
  #14  
Antiguo 16-07-2018
Avatar de gatosoft
[gatosoft] gatosoft is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Bogotá, Colombia
Posts: 833
Poder: 22
gatosoft Va camino a la fama
igual, no está de mas pensar en la solución tradicional: Definir una clase derivada de TIniFile, con la funcionalidad que requieres y a partir de ella definir los descendientes de los que hablas.

Cuando tienes una clase padre y muchos posibles descendientes que desconoces, es cuando comienzas a pensar en clases abstractas o en interfaces.
Responder Con Cita
  #15  
Antiguo 16-07-2018
Avatar de gatosoft
[gatosoft] gatosoft is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Bogotá, Colombia
Posts: 833
Poder: 22
gatosoft Va camino a la fama
Cita:
Empezado por bucanero Ver Mensaje
Hola Movorack, realmente no se a que te refieres con esto ....

Es que Movorack, Topx y yo, trabajamos en el mismo piso....
Responder Con Cita
  #16  
Antiguo 16-07-2018
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.257
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por gatosoft Ver Mensaje
Es que Movorack, Topx y yo, trabajamos en el mismo piso....
¿De verdad?
Responder Con Cita
  #17  
Antiguo 17-07-2018
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Muchas gracias gatosoft por toda la información aportada

Cita:
Empezado por gatosoft Ver Mensaje
Existe una técnica que te puede servir y es la de interceptores, pero como todo, no es para abusar de ella.

y funciona mas o menos así:

En la clausula Uses defines la unidad Inifiles, que contiene la implementación nativa del componente.

Después, defines la clase "interceptora" TIniFile (Tiene el mismo nombre de la nativa) la cual hereda de System.IniFiles.TIniFile (debes especificar la unidad).

Y en esta nueva clase, puedes definir nueva funcionalidad y sobreescribir la existente.
Si esta técnica es muy interesante y algunas veces la he utilizado para otros temas un poco mas simples, pero en este caso y como bien dices en el siguiente mensaje, a veces lo mas simple es lo mas eficaz, y he optado por realizar directamente mi clase con herencia tradicional.

Cita:
Empezado por gatosoft Ver Mensaje
igual, no está de mas pensar en la solución tradicional: Definir una clase derivada de TIniFile, con la funcionalidad que requieres y a partir de ella definir los descendientes de los que hablas.

Cuando tienes una clase padre y muchos posibles descendientes que desconoces, es cuando comienzas a pensar en clases abstractas o en interfaces.
Todo mi problema se lío, por no poder hacer en un principio override del constructor y a la hora de crear mi clase como no se hacia directamente desde la propia clase, si no desde una instancia genérica derivada de TINIFile, pues no llegaba a ejecutarse el método constructor propio de mi clase.



Cita:
Empezado por gatosoft Ver Mensaje
Yo también me encontré con ese problema del Nil, y por eso linkeaba la solución en ésta linea de código.

Código Delphi [-]
Initialization
  TMyIniFile.mydummy; //Me encontré con este error
En cuanto a crear a través de RTTI, vi el procedimiento y la explicación que habías comentado y si lo utilice, pero al principio no llego a funcionarme, creo que porque en tu código, tu guardabas la unidad y el nombre de la clase en una nueva variable para después hacer la búsqueda, y yo en su lugar use la propiedad ClassName de mi variable con la clase, omitiendo el de la unidad.

Después he realizado una pequeña modificación a tu código, para que no sea necesario hacer la búsqueda de la clase por su nombre, ya que a priori se tiene ya la clase y así se pueda utilizar directamente sin necesidad de hacer su búsqueda.
Y así, si ha funcionado también:

Código Delphi [-]
function config: TIniFile;
var
  RttiContext: TRttiContext;
  RttiType: TRttiInstanceType;
Begin
  if not Assigned(IniFile) then begin
    if Assigned(ClassIniFile) then begin
      RttiContext := TRttiContext.Create;
      try
        RttiType := RttiContext.GetType(ClassIniFile) as TRttiInstanceType;
        // si se ha localizado la la clase se llama al metodo create
        if Assigned(RttiType) then
          IniFile := RttiType.GetMethod('Create').Invoke(RttiType.MetaclassType, [IniFileName]).AsObject as TIniFile;
      finally
        RttiContext.free;
      end;
    end;
    //si no hay assignada ninguna clase especifica de TINIFile o no se ha conseguido
    //localizar la clase especifica, entoces se utiliza la clase TINIFile
    if not Assigned(IniFile) then
      IniFile := TIniFile.Create(IniFileName);
  end;
  Result := IniFile;
end;


Gracias nuevamente a todos los que han dedicado parte de su tiempo a este hilo
Un saludo
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Crear objetos mediante su clase coso Trucos 0 06-12-2008 00:37:15
duda al crear un descendiente de tpanel hibero OOP 1 23-05-2008 22:07:52
problema crear dll con clase rzf1983 Varios 9 08-11-2007 23:56:52
crear un evento en una clase? chelox OOP 4 06-06-2007 21:14:20
Crear clase. Basico de POO. DarkByte OOP 17 24-08-2005 18:37:21


La franja horaria es GMT +2. Ahora son las 01:44:26.


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
Copyright 1996-2007 Club Delphi