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 13-05-2010
Avatar de yapt
yapt yapt is offline
Miembro
 
Registrado: sep 2006
Ubicación: España
Posts: 258
Poder: 18
yapt Va por buen camino
Asignar 'array property' con record.elemento

Bueno,

en primer lugar disculpas por el título. La verdad es que no sé ni como describirlo de una forma concreta.

Se trata de lo siguiente (adjunto código muy sencillo y completo que he preparado para la ocasión). Solo hay que crear un form y un botón y al compilar, veo un bonito:

E2064 Left side cannot be assigned to

El caso es que es una clase que tiene un field que es un record y, como tal, tiene elementos dentro del record.

La cuestión es cómo acceder, de forma directa, a los elementos DENTRO del propio record.

Bueno, creo que con el ejemplo se vé claramente. Y no puede ser muy dificil, porque hay muchos componentes que usan esto (aunque no con Records, sino con Sub-Clases).

Cualquier ayuda será bien recibida.

Gracias.



Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TRecHijo = record
     campo1: string;
     campo2: Boolean;
  end;

  TPadre = class
  strict private
    FNumHijos:   byte;
    FHijos   :   array of TRecHijo;
    function  GetHijo(const Index: Integer): TRecHijo;
    procedure SetHijo(const Index: Integer; const Value: TRecHijo);
  published
    property HijosCount: Byte                             read FNumHijos;
  public
    constructor Create;
    destructor  Destroy; override;
    property Hijo[const Index: Integer]: TRecHijo read GetHijo  write SetHijo;
  end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
  private
    Padre : TPadre;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Padre.Hijo[1].campo1 := 'Hola';  //<<<<----- Aqui falla.
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Padre := TPadre.Create;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Padre.Free;
end;

{ TPadre }

constructor TPadre.Create;
begin
  inherited;
  FNumHijos  := 10;
  SetLength(FHijos, FNumHijos);
end;

destructor TPadre.Destroy;
begin
  inherited;
end;

function TPadre.GetHijo(const Index: Integer): TRecHijo;
begin
  result := FHijos[index];
end;

procedure TPadre.SetHijo(const Index: Integer; const Value: TRecHijo);
begin
  FHijos[Index] := Value;
end;

end.

Última edición por yapt fecha: 13-05-2010 a las 14:38:17. Razón: Había olvidado poner el error.
Responder Con Cita
  #2  
Antiguo 13-05-2010
Avatar de Lord Delfos
Lord Delfos Lord Delfos is offline
Miembro
 
Registrado: ene 2008
Ubicación: Tandil, Argentina
Posts: 558
Poder: 17
Lord Delfos Va por buen camino
Ah... Es que los registros son medio HDP...

Verás, cuando uno llama a la propiedad izquierdo, Delphi va a llamar al GetHijo ¿Verdad? Bueno, pero GetHijo es una función, y la función devuelve una copia del registro original. Y esa copia es, por defecto, de sólo lectura. Ahí está el problema.

Si uno hace algo así:

Código Delphi [-]

type
  TRec = record
     campo1: string;
     campo2: Boolean;
  end;

  type PRec = ^TRec; // <---------------------------

  type TAlgo = class
    private
      FDatos: array of TRec;
      function GetDato(const Indice: Integer): PRec;
      procedure SetDato(const Indice: Integer; const Valor: PRec);
    public
      property Datos[const Indice: Integer]: PRec read GetDato write SetDato;
    end;

function TAlgo.GetDato(const Indice: Integer): PRec;
begin
  Result:= @FDatos[Indice];
end;

procedure TAlgo.SetDato(const Indice: Integer; const Valor: PRec);
begin
  FDatos[Indice]:= Valor^;
end;

MiObjeto.Datos[3].Campo1:= 'Hola'; // <--- funciona

Esto funciona, pero ¿porqué? Bueno, porque ahora estás devolviendo un puntero al original, y como la dereferencia en los registros (el ^) es automática, pues termina andando sin que tengas que agregar el ^ al hacer la asignación.

¿Se entiende lo que digo? Espero que sí, sino pues... que te ayude otro. Digo, volvé a preguntar y trato de explicarlo mejor.

Saludongos.
Responder Con Cita
  #3  
Antiguo 13-05-2010
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
Probando. No hacer caso.
Responder Con Cita
  #4  
Antiguo 13-05-2010
Avatar de yapt
yapt yapt is offline
Miembro
 
Registrado: sep 2006
Ubicación: España
Posts: 258
Poder: 18
yapt Va por buen camino
jejejejeje... Que buen humor. Da gusto...

Veo el código y lo entiendo (el código). Aunque se me escapa un poco el concepto.



Cita:
Empezado por Lord Delfos Ver Mensaje
Verás, cuando uno llama a la propiedad izquierdo
A que te refieres con la propiedad IZQUIERDO ?

Cita:
Empezado por Lord Delfos Ver Mensaje
Delphi va a llamar al GetHijo ¿Verdad? Bueno, pero GetHijo es una función, y la función devuelve una copia del registro original. Y esa copia es, por defecto, de sólo lectura
Ok, esto lo entiendo... pero entonces porque esto SI funciona ?:

Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
  HolaHola : TRecHijo;
begin
  Padre.Hijo[1] := HolaHola;  //<<<<----- Esto de aquí... ???
end;

Porque tambien Padre.Hijo[1] llaman al GetHijo, no ?

Muchas gracias.... así da gusto...

Responder Con Cita
  #5  
Antiguo 13-05-2010
Avatar de yapt
yapt yapt is offline
Miembro
 
Registrado: sep 2006
Ubicación: España
Posts: 258
Poder: 18
yapt Va por buen camino
Thumbs up

Bueno, en cualquier caso y por no incordiar mucho (pues ya lo tengo funcionando con los consejos de Lord Delfos) ya tengo lectura para esta noche:

http://docwiki.embarcadero.com/RADStudio/en/Properties

Lo voy a leer detenidamente.

Muchas gracias de nuevo.
Responder Con Cita
  #6  
Antiguo 13-05-2010
Avatar de Lord Delfos
Lord Delfos Lord Delfos is offline
Miembro
 
Registrado: ene 2008
Ubicación: Tandil, Argentina
Posts: 558
Poder: 17
Lord Delfos Va por buen camino
Cita:
Empezado por yapt Ver Mensaje
A que te refieres con la propiedad IZQUIERDO ?
Eh... Quise decir cuando la propiedad es llamada del lado izquierdo de una asignación. Que es cuando se llama al gettter y no al setter (el GetHijo, vamos).

Cita:
Empezado por yapt Ver Mensaje
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
  HolaHola : TRecHijo;
begin
  Padre.Hijo[1] := HolaHola;  //<<<<----- Esto de aquí... ???
end;

Porque tambien Padre.Hijo[1] llaman al GetHijo, no ?
A ver, a ver. Según entiendo yo.

Código Delphi [-]
Padre.Hijo[1]:= AlgunRegistro;

Sería:

Código Delphi [-]
Temporal:= Padre.FHijo[1];
Temporal:= AlgunRegistro;
Padre.FHijo[1]:= Temporal;

Ahora:

Código Delphi [-]
Padre.Hijo[1].campo1:= 'Hola';

Sería:
Código Delphi [-]
Temporal:= Padre.FHijo[1];
Temporal2:= Temporal.campo1;
Temporal2:= 'Hola';
Padre.FHijo[1]:= Temporal;

¡Ajá! Pero si asignamos Temporal (no Temporal2) a FHijo[1], entonces perdemos la asignación a campo1. ¿no?

Por eso, el compilador se niega a aceptar hacer tal cosa. En otros lenguajes, como C#, esto está permitido, aunque el valor NO es asignado. Es decir, pasa lo mismo que en el ejemplo de arriba.

Porqué motivo el compilador no hace Padre.FHijo[1].campo1:= Temporal2, te preguntarás. Pues porque la propiedad de clase devuelve un registro, no un string. Es decir, el GetHijo devuelve todo un registro, una copia del original, y sobre esa copia vos querés cambiar el valor. Recordemos que la propiedad trata sobre un registro, así que el SetHijo supone que le vas a pasar todo el registro, no solamente un campo...

En tu ejemplo en el que asignás un registro completo, ahí no hay problemas porque, precisamente, la propiedad trabaja con un registro, así la definiste vos. No sé si se entiende...

O al menos eso es lo que yo entiendo.

Última edición por Lord Delfos fecha: 13-05-2010 a las 21:03:19.
Responder Con Cita
  #7  
Antiguo 13-05-2010
Avatar de yapt
yapt yapt is offline
Miembro
 
Registrado: sep 2006
Ubicación: España
Posts: 258
Poder: 18
yapt Va por buen camino
Cita:
Empezado por Lord Delfos Ver Mensaje
No sé si se entiende...
Se entiende PERFECTO Lord Delfos. Y los ejemplos con sus desgloses.... muy didácticos.

Muchas gracias.
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
Buscar un elemento en un array sin recorrerlo David OOP 3 23-07-2011 16:15:40
Comprobar si existe elemento en el Array Cecil Varios 2 17-02-2008 06:37:25
Actualizar Caption de un elemento de Array of TLabel's gluglu Varios 2 15-06-2007 18:24:16
quitar elemento de un array dinámico elcigarra OOP 2 08-09-2006 23:30:34
Como Asignar Variable Tipo Array de Tform a otro Array del Mismo tipo morfeo21 Varios 5 17-08-2004 17:39:51


La franja horaria es GMT +2. Ahora son las 14:30:52.


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