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

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 05-06-2003
shaktale shaktale is offline
Miembro
 
Registrado: may 2003
Ubicación: Euskal Herria
Posts: 39
Poder: 0
shaktale Va por buen camino
Metodos que devuelven referencias a sí mismos

Saludos a todos,

Estoy haciendo un cosa un poco rara, se trata más de probar que de que sea realmente util, pero he llegado a un punto en el que no entiendo por qué me está fallando.

La idea es la siguiente:

He definido una clase TTabla, que tiene (entre otros) los siguientes metodos:

Código:
function TTabla.AddTitulos(t:array of THTMLDoc):TTabla;
begin
  ...
  Result:=Self;
end;

function TTabla.AddLinea(l:array of THTMLDoc):TTabla;
begin
  ...
  Result:=Self;
end;
La idea de esto es que te devulva una referencia a si mismo para poder aplicar varias veces estos metodos de la siguiente forma:

Código:
t:=TTabla.Create.AddTitulos([TLinea.Create('t')]).AddLinea([TLinea.Create('l1')])
el problema está en que sí que puedo aplicar una vez, es decir algo como esto funciona bien:

Código:
t:=TTabla.Create.AddTitulos([TLinea.Create('t')]);
pero si le pongo después otro AddLinea me da un error de acceso a la mem.

¿Alguien ha tenido alguna vez un problema similar?

Muchas gracias por vuestro tiempo
Responder Con Cita
  #2  
Antiguo 05-06-2003
Avatar de delphi.com.ar
delphi.com.ar delphi.com.ar is offline
Federico Firenze
 
Registrado: may 2003
Ubicación: Buenos Aires, Argentina *
Posts: 5.932
Poder: 27
delphi.com.ar Va por buen camino
Sinceramente, creo que lo que vas a lograr es conglomerar el código y va a quedar poco claro.
¿Porqué hacer algo tan feo y puedes escribirlo prolijamente en varias líneas? (Es solo una opinión personal )
Yo tengo como norma, escribir el código lo más claro posible, para cualquier programador que retome el sistema pueda entenderlo sin problemas.

Saludos!
__________________
delphi.com.ar

Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla.
Responder Con Cita
  #3  
Antiguo 05-06-2003
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Esto me recuerda la forma en que se creaban los menús en Turbo Visión. Toda la estructura se declaraba en una solo llamada a procedimiento, algo así como:

Código:
CreateMainMenu(
  CreateMenu('item', 'item', 'item'),
  CreateMenu('item', 'item', 'item'),
  CreateMenu('item', 'item',
    CreateSubMenu('item', 'item',
      CreateSubMenu('item', 'item')
    )
  ),
  'item'
)
Si no están bien balanceados mis paréntesis es natural. Eso es lo que pasaba siempre.

// Saludos
Responder Con Cita
  #4  
Antiguo 06-06-2003
Avatar de gatosoft
[gatosoft] gatosoft is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Bogotá, Colombia
Posts: 833
Poder: 21
gatosoft Va camino a la fama
Lightbulb

t:=TTabla.Create.AddTitulos([TLinea.Create('t')]).AddLinea([TLinea.Create('l1')])


La idea es bien interesante... yo creo que el error esta en que la funcion addLinea tiene dentro de si una operacion que realizar... supongo que el compilador intenta realizar las operaciones mas internas primero y despues las mas externas.... (bueno de hecho todos trabajan asi)

Por lo tanto:

TLinea.Create('l1') se ejecuta primero, y luego, intenta pasarla a la funcion AddLinea, que aun no ha sido creada.... y entonces ocurre el "error read address FFFFFFFF" que frecuentemente es el error de que sale cuando no se ha instanciado un objeto.


No estoy seuro, pero el problema debe estar por ahí.


Saludos...
Responder Con Cita
  #5  
Antiguo 06-06-2003
shaktale shaktale is offline
Miembro
 
Registrado: may 2003
Ubicación: Euskal Herria
Posts: 39
Poder: 0
shaktale Va por buen camino
En primer lugar gracias por las respuestas.

Ya se que no es una manera muy elegante de programar, pero como ya dije lo queria hacer más en plan de prueba que por su utilidad o claridad.

Con respecto a lo que comentas, gatosoft, supongo que andará por ahi el tema, pero entonces lo que no entiendo es por qué SI que funciona lo siguiente:

Código:
t:=TTabla.Create.AddTitulos([TLinea.Create('t')]);
saludos
Responder Con Cita
  #6  
Antiguo 06-06-2003
Avatar de gatosoft
[gatosoft] gatosoft is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Bogotá, Colombia
Posts: 833
Poder: 21
gatosoft Va camino a la fama
Wink

Bueno, si trtamos de analizar paso a paso el trabajo del compilador yo diria, sobre esta linea de codigo:


t:=TTabla.Create.AddTitulos([TLinea.Create('t')]).AddLinea([TLinea.Create('ll')])


Primero resuelve los parentesis:

TLinea.Create('t') y TLinea.Create('ll')

Luego, para resolver esta linea, daria prioridad al constructor:

TTabla.Create.AddTitulos(...).AddLinea(...)

pero una vez resuelto eso, el tendria que resolver, si solucionar primero el AddTitulos o el AddLinea:

¿Como sabria el cual tiene prioridad?

Resolver de Izquierda a derecha o de derecha a Izquierda en caso de empate.....

tal vez lo mas obvio , en teoria de objetos (o al menos para mi), seria que resolviera de Derecha a Izquierda....


Objeto.funcion1.funcion2.funcion3
=============>>

Pues el obejto es el que envia los mensajes y es de donde nacen las propedades y los metodos.... En este caso el compilador no tendria problemas... no deberia marcar error en tu codigo

Pero y si intenta resolver la situación en la otra dirección?:

Objeto.funcion1.funcion2.funcion3
<<============

No se por que habria de hacerlo asi.... pero tal parece que asi esta funcionando, o si no...¿de que otra manera podria decir que el objeto no ha sido creado? (creo haber entendido que ese es el error).


Como dices... este ejemplo es mas instructivo que aplicativo.... pues el problema se resuelve partiendo en dos lines tu codigo,pero nos puede ayudar a enteder de alguna forma como trabaja el compilador en estos casos...


suerte.
Responder Con Cita
  #7  
Antiguo 06-06-2003
shaktale shaktale is offline
Miembro
 
Registrado: may 2003
Ubicación: Euskal Herria
Posts: 39
Poder: 0
shaktale Va por buen camino
Post

Tengo que revisar el código porque parece que el problema no está (sólo) en la llamada en cuestión sino también en qué otros objetos de tipo THTMLDoc hay creados.

Para quien le interese: lo que trataba de hacer es de crear una estructura (THTMLDoc) que representa un fichero HTML, este objeto puede contener a su vez otros objetos de tipo THTMLDoc de forma recursiva y generar así páginas HTML en forma de objtos que se van añadiendo. De hecho me funcionaba bien teniendo los métodos Add como procedures, pero había que probar...

...paranoias que me monto...

Gracias otra vez
Responder Con Cita
  #8  
Antiguo 07-06-2003
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 27
jachguate Va por buen camino
que tiempos aquellos de Turbo Vision...

El problema no está en el código que has mostrado en si....

Creo que debes revisar cómo manejas la memoria... pues por allí encontraras seguramente algun bug...

Para ilustrarlo, he hecho este ejemplo, totalmente inutil... pero que compila y funciona perfectamente...

Primero crea un unit, y pegá el siguiente código:


Código:
unit Unit2;

interface

Type
  TJachElem = Class
  private
    a : Integer;
    b : Integer;
    function GetaValue: Integer;
    function GetbValue: Integer;
  public
    Constructor Create(aa, ab: Integer);
    Destructor Destroy; override;
    Property aValue : Integer read GetaValue;
    Property bValue : Integer read GetbValue;
  end;

  TJachTable = Class
  private
    Elem1 : TJachElem;
    Elem2 : TJachElem;
    function GetElem1a: Integer;
    function GetElem1b: Integer;
    function GetElem2a: Integer;
    function GetElem2b: Integer;
  public
    Constructor Create;
    Destructor Destroy; override;
    Function AddElem1(aElem : TJachElem) : TJachTable;
    Function AddElem2(aElem : TJachElem) : TJachTable;
    Property Elem1a : Integer read GetElem1a;
    Property Elem1b : Integer read GetElem1b;
    Property Elem2a : Integer read GetElem2a;
    Property Elem2b : Integer read GetElem2b;
  end;

implementation
uses SysUtils;

{ tJachElem }

constructor tJachElem.Create(aa, ab: Integer);
begin
  inherited create;
  a := aa;
  b := ab;
end;

destructor tJachElem.Destroy;
begin

  inherited;
end;

function TJachElem.GetaValue: Integer;
begin
  Result := a;
end;

function TJachElem.GetbValue: Integer;
begin
  Result := b;
end;

{ tJachTable }

function TJachTable.AddElem1(aElem: TJachElem): TJachTable;
begin
  if assigned(Elem1) Then
    Elem1.Free;
  Elem1 := aElem;
  Result := Self;
end;

function TJachTable.AddElem2(aElem: TJachElem): TJachTable;
begin
  if assigned(Elem2) Then
    Elem2.Free;
  Elem2 := aElem;
  Result := Self;
end;

constructor tJachTable.Create;
begin
  inherited;
end;

destructor tJachTable.Destroy;
begin
  if Assigned(Elem1) Then
    Elem1.Free;
  if assigned(Elem2) Then
    Elem2.Free;
  inherited;
end;

function TJachTable.GetElem1a: Integer;
begin
  if not Assigned(Elem1) Then
    raise Exception.Create('No se ha asignado Elem1!');
  Result := Elem1.aValue;
end;

function TJachTable.GetElem1b: Integer;
begin
  if not Assigned(Elem1) Then
    raise Exception.Create('No se ha asignado Elem1!');
  Result := Elem1.bValue;
end;

function TJachTable.GetElem2a: Integer;
begin
  if not Assigned(Elem2) Then
    raise Exception.Create('No se ha asignado Elem2!');
  Result := Elem2.aValue;
end;

function TJachTable.GetElem2b: Integer;
begin
  if not Assigned(Elem2) Then
    raise Exception.Create('No se ha asignado Elem2!');
  Result := Elem2.bValue;
end;

end.

Luego en otro unit podes hacer esta llamada:

Código:
Var
  FTabla : TJachTable;

Begin
  FTabla := TJachTable.Create.AddElem1(TJachElem.Create(1, 2)).AddElem2(TJachElem.Create(2, 1));
  try
    Label1.Caption := IntToStr(FTabla.Elem1a);
    Label2.Caption := IntToStr(FTabla.Elem1b);
    Label3.Caption := IntToStr(FTabla.Elem2a);
    Label4.Caption := IntToStr(FTabla.Elem2b);
  finally
    FTabla.Free;
  end;
End;
y todo funciona perfectamente.

Hasta luego.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #9  
Antiguo 07-06-2003
Avatar de marto
marto marto is offline
Miembro
 
Registrado: may 2003
Ubicación: Barcelona, Catalunya
Posts: 882
Poder: 21
marto Va por buen camino
Estoy completamente deacuerdo con jachguate, tienes que estar haciendo algo mal dentro de tu código.
No veo que el order de resolución del compilador tenga que ver con el error, ya que éste se produce en ejecución, por lo tanto el compilador tiene que haber resuleto todo bíen. Lo que no tendría sentido es se ejecutase de "derecha a izquierda".
Conclusión.... lo más probable es que hagas algo mal con tus referencias, o que te olvides de instanciar algo o que algun puntero se te quede mirando a vetetuasaberdonde. de todas maneras, sin ver el código es complicado aventurarse a saber qué es
__________________
E pur si muove
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


La franja horaria es GMT +2. Ahora son las 17:58:23.


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