Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Compara Valores de Objetos de la misma clase (https://www.clubdelphi.com/foros/showthread.php?t=64554)

Carmelo Cash 07-04-2009 16:09:44

Compara Valores de Objetos de la misma clase
 
Hola Foro:
Necesito comparar los valores que tengo en dos objetos de la misma clase.
Cuando traigo los datos de un cliente los guardo en dos objetos, Cliente y ClienteViejo, entonces me queda.

Cliente.Nombre:='pepe'
Cliente.Direccion:='cucha cucha 444'

ClienteViejo.Nombre:='pepe'
ClienteViejo.Direccion:='cucha cucha 444'

lo que necesito hacer al cerrar el formulario es algo como esto

if Cliente.ValoresdeTodosLosCampos<>ClienteViejo.ValoresdeTodosLosCampos then grabar;

De esta manera mando a grabar solamente si hubo una modificación en.

Eso es todo, desde ya gracias por su atención.

delphi.com.ar 07-04-2009 16:24:18

Como opción rápida, se me ocurre que todos los campos de la clase lo tengas almacenados en un record, crear un método que sea "Compare", e internamete utilizar la función CompareMem para comparar los valores de los records.

Saludos!

Neftali [Germán.Estévez] 07-04-2009 16:25:50

Lo que yo he hecho en algun caso similar a este es crear un método en la clase (en este caso cliente) que devuelve el objeto como string.

Código Delphi [-]
  Self.FAsString := Self.FCodigo + '|' + Self.FDireccion + '|' + ...

Utilizando un separador.
En mi caso me sirve para temas de Debug, de exportación y para cuestiones como estas. En ese caso vadría con hacer algo similar a esto.

Código Delphi [-]
  if (Cliente.AsString <> ClienteViejo.AsString) then begin 
    ...

No es nada muy sofisticado, pero a mi me funciona.

NOTA: En mi caso lo tengo a nivel de una clase Base que recorre todos los campos y hace la operación de concatenación, de forma que no se implementa en cada una de las clases, pero la idea es la misma.

Un saludo.

Crandel 07-04-2009 16:30:59

Desde la version Delphi 2006 se ha incluido la sobrecarga de operadores. Lo que te permite definir la operación de igualación entre dos registros y verificar si son iguales.

Supongamos que tienes el registro TCliente
Código Delphi [-]
TCliente = record
  Nombre: string;
  Direccion: string;
end;

entonces sobrecargas el operados Equal para poder hacer comparaciones entre dos registros

Código Delphi [-]
TCliente = record
  Nombre: string;
  Direccion: string;

  class operator Equal( c1, c2 : TCliente): bool;
end;

y lo implementas asi:
Código Delphi [-]
class operator TCliente.Equal( c1, c2 : TCliente): bool;
begin  
   Result := (c1.Nombre = c2.Nombre)  and (c1.Direccion = c2.Direccion);
end;

* El codigo no lo he verificado en delphi asi que puede tener errores, pero es la idea.

Carmelo Cash 07-04-2009 17:12:34

Listo
 
Quedó así, una función dentro del objeto que devuelve verdadero o false comparando todos los campos.

Código Delphi [-]
function tClientes.Equals(recDatos: tClientes): boolean;
begin
  result:=
  (self.Nombre = recDatos.Nombre) and
  (self.Direccion = recDatos.Direccion) ;
end;


-- Boton grabar --

Código Delphi [-]
if not ClienteActual.Equals(clienteViejo) then grabar;

Gracias a todos los que participaron. :cool:

JoseAntonio 07-04-2009 18:07:12

En este caso si seria interesante usar las RTTI de delphi, aunque no soy un experto en el tema

delphi.com.ar 07-04-2009 18:11:27

Cita:

Empezado por JoseAntonio (Mensaje 344226)
En este caso si seria interesante usar las RTTI de delphi, aunque no soy un experto en el tema

El tema es decidir que propiedades evaluar y cuales no. Por otro lado puede ser mas práctico si lo implementamos muchas veces, pero poco perfrormante.

Saludos!

roman 07-04-2009 18:53:17

Si estamos trabajado con objetos, ¿por qué no hacer algo así?

Código Delphi [-]
type
  TMiObjeto = class
  private

    FPropiedad: TTipoDeDatos;
    procedure SetPropiedad(Valor: TTipoDeDatos);

  public
    Modificado: Boolean;
    property Propiedad: TTipoDeDatos write SetPropiedad;
  end;

implementation

procedure TMibjeto.SetPropiedad(Valor: TTipoDeDatos);
begin
  FPropiedad := Valor;
  Modificado := true;
end;

Claro que hay que poner un método de acceso para cada propiedad (cosa que es bastante común) pero al final, la comprobación es tan sencilla como

Código Delphi [-]
if MiObjeto.Modificado then
  Grabar;

sin tener que comparar campo por campo.

--------------------------------------------------------------------------------------

Cita:

Empezado por delphi.com.ar
que todos los campos de la clase lo tengas almacenados en un record, crear un método que sea "Compare", e internamete utilizar la función CompareMem para comparar los valores de los records.

Pero, ¿esto serviría si tenemos valores string? Es decir, creo que todos los valores que nos interesen para la comparación tendrían queser de longitud fija ¿no?

// Saludos

Neftali [Germán.Estévez] 07-04-2009 19:10:47

Cita:

Empezado por roman (Mensaje 344247)
Si estamos trabajado con objetos, ¿por qué no hacer algo así

El problema que le veo a esto Román, es que sólo podemos comparar u objeto consigo mismo (por decirlo así), pero no nos serviría para comparar dos objetos distintos físicamente.

En el caso de Cliente y ClienteViejo, son dos objetos de la clase cliente distintos.

roman 07-04-2009 19:14:29

Tienes razón Neftalí; es que me parece que en el fondo no me cuadra lo de usar dos objetos para lo mismo y subconcientemente lo omití :D Pero claro que bajo esas condiciones no aplica lo que digo.

// Saludos

delphi.com.ar 07-04-2009 19:37:19

Cita:

Empezado por roman (Mensaje 344247)
Pero, ¿esto serviría si tenemos valores string? Es decir, creo que todos los valores que nos interesen para la comparación tendrían queser de longitud fija ¿no?

Así es, creí haberlo aclarado :confused:.

Te dejo algo para marearse un ratito, cositas que hace el compilador:
Código Delphi [-]
type
  TData = record
    Field1: string;
    Field2: string
  end;
var
  D1, D2: TData;
begin
  D1.Field1 := 'Hola Mundo!';
  D1.Field2 := '123'; {Probar cambiando los valores, o tomandolos de un edit}

  D2.Field1 := 'Hola Mundo!';
  D2.Field2 := '123';

  Caption := IfThen(CompareMem(@D1, @D2, SizeOf(TData)), '=', '<>');

Crandel 07-04-2009 22:47:48

Cita:

Empezado por Carmelo Cash (Mensaje 344201)
-- Boton grabar --

Código Delphi [-]
if not ClienteActual.Equals(clienteViejo) then grabar;

Una sentencia equivalente a la que acabas de escribir pero usando el operador mismo seria asi:

Código Delphi [-]
if not (ClienteActual = clienteViejo) then grabar;

de esta misma forma puedes definir el operador <> y todos los restantes.

Crandel 07-04-2009 23:04:18

y en el caso de registros mas complejos con varios atributos se puede aprovechar la excelente funcion CompareMem (gracias fede ya no me la acordaba)

entonces la definicion del operados Equal te queria asi:

Código Delphi [-]
class operator TCliente.Equal( c1, c2 : TCliente): bool;
begin  
   Result := CompareMem(@c1, @c2, SizeOf(TCliente));
end;

y para el caso del operador <>

Código Delphi [-]
class operator TCliente.NotEqual( c1, c2 : TCliente): bool;
begin  
   Result := not (c1 = c2);
end;

nunca entendi porque este no es el efecto por defecto :rolleyes:

y ahora si tienes exactamente la sentecia que querias arriba:

Código Delphi [-]
if ClienteActual <> clienteViejo then grabar;

delphi.com.ar 07-04-2009 23:09:18

Cita:

Empezado por Crandel (Mensaje 344282)
entonces la definicion del operados Equal te queria asi:

Solo si el record tiene valores de longitud fija, si tiene pascal strings, null terminated string NO, pero si en su lugar lo cambias por un array de chars estático, si!

Fíjate que pasa en el ejemplo que pasé si los valores no son cargados desde constantes, haciendo algo como esto:
Código Delphi [-]
  D1.Field2 := Edit1.Text;
  D2.Field2 := Edit2.Text;

Crandel 07-04-2009 23:47:57

Cita:

Empezado por delphi.com.ar (Mensaje 344283)
Solo si el record tiene valores de longitud fija, si tiene pascal strings, null terminated string NO, pero si en su lugar lo cambias por un array de chars estático, si!

POr eso digo no usar el CompareMem en este caso :D Eso me pasa por no seguir el hilo de la discución :p


La franja horaria es GMT +2. Ahora son las 23:18:15.

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