Tema: Delphi y OO
Ver Mensaje Individual
  #8  
Antiguo 02-03-2011
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Reputación: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por Paulao Ver Mensaje
No, realmente mi gustaria de entender esto. Si es lo mismo que las variables de instancia en Java y etc... Para sirve las property, su uso y etc...
A ver, advierto que no he leido lo anterior así que quizá repita o diga algo que no viene del todo al caso.

Hasta donde entiendo y recuerdo, las propiedades (property) en delphi no tienen equivalente en Java. Sólo he visto algo parecido en PHP 5, y tiene sus bemoles.

Podríamos decir, aunque no es del todo cierto, que una propiedad es una forma elegante de acceder a una variable de instancia privada.

En Java puedes tener, por poner un ejemplo, la clase Persona con un campo privado (variable de instancia) llamado nombre. En este tipo de lenguajes, para acceder a tal variable, lo usual es definir métodos de acceso como getNombre (para leer el valor) y setNombre (para establecer el valor). Así, podrías tener un código de este estilo:

Código:
nombre = p.getNombre();

// o bien

p.setNombre("roman");
siendo p una variable de tipo Persona. Siendo nombre una variable privada de la clase Persona, no puedes, por ejemplo, hacer esto:

Código:
p.nombre = "roman";
En delphi, también puedes tener tu clase TPersona y una variable de instancia privada FPersona y correspondientes métodos de acceso:

Código Delphi [-]
TPersona = class
private
  FNombre: String;

public
  function GetNombre(): String;
  procedure SetNombre(S: String);
end;

Podrías hacer uso de los métodos al igual que en Java:

Código Delphi [-]
Nombre := P.GetNombre();

// o bien

P.SetNombre('roman');

Pero, en delphi puedes hacer algo mucho mejor. Puedes declarar una propiedad pública Nombre que use esos métodos de acceso:

Código Delphi [-]
TPersona = class
private
  FNombre: String;

public
  function GetNombre(): String;
  procedure SetNombre(S: String);

  (* read indica el método para leer el valor      *)
  (* write indica el método para escribir el valor *)
  property Nombre: String read GetNombre write SetNombre;
end;

En código puedes usar directamente dicha propiedad:

Código Delphi [-]
P.Nombre := 'roman';

Sintácticamente hablando -y ésta es la gran ventaja- es como si "accedieras" directamente al campo privado:

Código Delphi [-]
P.FNombre := 'roman';  // aquí el compilador marcará error pues FNombre es privada a la clase.

pero, en realidad, el compilador, cuando ve la línea

Código Delphi [-]
P.Nombre := 'roman';

genera este código: (o parecido)

Código Delphi [-]
P.SetNombre('roman');

Esto es, aunque en apariencia estamos asignando la cadena 'roman' a la variable privada FNombre, en realidad la asignación pasa por llamar a la función SetNombre.

Lo mismo si queremos conocer el valor de la variable privada:

Código Delphi [-]
Nombre := P.Nombre;

Al hacer esto, el compilador genera la llamada:

Código Delphi [-]
Nombre := P.GetNombre();

En resumen, las propiedades en delphi nos permiten acceder a atributos de un objeto como si lo hiciéramos directamente, pero siempre pasando por métodos de acceso.

La razón de esto o su finalidad pues es la misma que en Java y otros lenguajes: proteger el ingreso y egreso de datos.

Siguiendo el ejemplo, el método SetNombre podría estar definido así:

Código Delphi [-]
procedure TPersona.SetNombre(S: String);
begin
  FNombre := S;
end;

Pero también podría ser así:

Código Delphi [-]
procedure TPersona.SetNombre(S: String);
begin
  FNombre := UpperString(S);
end;

forzando así, que los nombres estén en mayúsculas.

Ahora bien, dije al principio que definir una propiedad como una forma de acceder a una variable privada no sería del todo exacto.

Un propiedad no necesariamente refleja directamente el valor de un campo del objeto. Continuando con el ejemplo, podríamos tener nuestra clase:

Código Delphi [-]
TPersona = class
private
  FNombre: String;
  FApellidos: String;

public
  function GetNombre(): String;
  procedure SetNombre(S: String);

  function GetApellidos(): String;
  procedure SetApellidos(S: String);

  property Nombre: String read GetNombre write SetNombre;
  property Apellidos: String read GetApellidos write SetApellidos;
end;

con dos propiedades: Nombre y Apellidos.

¿Qué tal si queremos saber el nombre completo de la persona?

Podríamos definir una función que haga el trabajo:

Código Delphi [-]
TPersona = class
private
  ...
public
  ...
  function GetNombreCompleto(): String;
end;

La función simplemente devolvería la concatenación del nombre y los apellidos. Podemos usar el método como siempre:

Código Delphi [-]
NombreCompleto := P.GetNombreCompleto();

Pero podemos hacerlo más elegante (y legible) definiendo una propiedad:

Código Delphi [-]
TPersona = class
private
  ...
public
  ...
  function GetNombreCompleto(): String;

  property NombreCompleto: String read GetNombreCompleto:
end;

con la cual el código se hace más limpio:

Código Delphi [-]
NombreCompleto := P.NombreCompleto;

En este caso, NombreCompleto es un atributo de la clase TPersona, pero no hay una variable de instancia que refleje su valor. Más aún, al no haber declarado un método Set (cláusula write), la propiedad es de sólo lectura; no hay manera, como es lógico, de asignar un valor a P.NombreCompleto.

Así pues, las propiedades en delphi no son más que aditamentos sintácticos o sintactic sugar, es decir, elementos de sintaxis que son prescindibles pero que hacen la vida más sencilla.

Nota, por último, que la declaración de la clase puede hacerse aún más prolija si se mueven los métodos de acceso a una sección privada:

Código Delphi [-]
TPersona = class
private
  FNombre: String;
  FApellidos: String;

  function GetNombre(): String;
  procedure SetNombre(S: String);

  function GetApellidos(): String;
  procedure SetApellidos(S: String);

  function GetNombreCompleto(): String;

public
  property Nombre: String read GetNombre write SetNombre;
  property Apellidos: String read GetApellidos write SetApellidos;
  property NombreCompleto: String read GetNombreCompleto:
end;

// Saludos

Última edición por roman fecha: 02-03-2011 a las 18:49:59.
Responder Con Cita