FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
|||
|
|||
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; Código:
t:=TTabla.Create.AddTitulos([TLinea.Create('t')]).AddLinea([TLinea.Create('l1')]) Código:
t:=TTabla.Create.AddTitulos([TLinea.Create('t')]); ¿Alguien ha tenido alguna vez un problema similar? Muchas gracias por vuestro tiempo |
#2
|
||||
|
||||
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. |
#3
|
||||
|
||||
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' ) // Saludos |
#4
|
||||
|
||||
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... |
#5
|
|||
|
|||
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')]); |
#6
|
||||
|
||||
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. |
#7
|
|||
|
|||
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 |
#8
|
||||
|
||||
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; Hasta luego.
__________________
Juan Antonio Castillo Hernández (jachguate) Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate |
#9
|
||||
|
||||
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 |
|
|
|