Ir al contenido


Foto

Concepto: Herencia


  • Por favor identifícate para responder
10 respuestas en este tema

#1 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 17 diciembre 2008 - 05:47

Hola

En esta oportunidad voy a hablar sobre la herencia de clases.

¿Que es la herencia de clases?

En términos generales la herencia es una propiedad que permite que algún objeto sea creado a partir de otros ya existentes, obteniendo características (métodos y atributos) similares al objeto base.

La herencia es uno de los mecanismos de la programación orientada a objetos, por medio del cual una clase se deriva de otra, de manera que extiende su funcionalidad y una de sus funciones más importantes es la de proveer Polimorfismo que es la capacidad que tienen los objetos de una clase de responder al mismo mensaje o evento en función de los parámetros utilizados durante su llamado.

Bueno, para no aburrirlos con teoría que bien pueden leer en cualquier sitio web o en la ayuda de Delphi :D, vamos a ver un ejemplo de esto.


  • 1

#2 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 17 diciembre 2008 - 05:52

1. Creamos un nuevo proyecto.
2. Agregamos en la forma un botón y un Memo.
3. Creamos una clase con el clasico ejemplo de Mamifero.



delphi
  1.   TMamifero = class(TObject)
  2.      Nombre: string;
  3.      Patas: integer;
  4.      function MuestraDatos:string;
  5.   end;



4. Ahora escribimos algo de código en la función MuestraDatos (puedes hacerlo posicionandote en la función y presionando con Ctrl+Shift+C)



delphi
  1. { TMamifero }
  2.  
  3. function TMamifero.MuestraDatos: string;
  4. begin
  5.   result := nombre + ' tiene ' + inttostr(patas) + ' patas';
  6. end;



5. En el evento onClick del botón escribimos este código.



delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Mamifero: TMamifero; //Asignamos una variable del tipo TMamifero
  4. begin
  5.   Mamifero := TMamifero.Create; //Creamos el objeto
  6.   with Mamifero do begin
  7.     Nombre := 'Perro';
  8.     Patas := 4;
  9.     Memo1.Lines.Add(MuestraDatos); //Mostramos en el memo el resultado de la función MuestraDatos
  10.   end;
  11. end;



Bueno, hasta aquí podrán observar que hemos creado una clase base TMamifero, ahora vamos a crear una clase que va a heredar de la clase base sus caracteristicas.

6. Creamos una clase de nombre TPerro la cual decenderá de la clase TMamifero.



delphi
  1.   TMamifero = class(TObject)
  2.      Nombre: string;
  3.      Patas: integer;
  4.      function MuestraDatos:string; virtual;
  5.   end;
  6.  
  7.   TPerro = class(TMamifero)
  8.      Raza: string;
  9.      function MuestraDatos:string; override;
  10.   end;



Esta clase hereda de la clase TMamiferos El Nombre y las Patas, pero se agrega a ella el dato Raza y la función MuestraDatos que tiene el mismo nombre que la función base. Hay que notar que se han escrito dos palabras reservadas (virtual en la clase base y override en la clase derivada) adelante de cada una de las funciones, esto es necesario cuando una función en la clase base es redefinida en la clase derivada.

7. Ahora escribimos algo de código en la función MuestraDatos de la clase derivada, la cual requerimos que tenga diferente retorno (puedes hacerlo posicionandote en la función y presionando con Ctrl+Shift+C)



delphi
  1. function TPerro.MuestraDatos: string;
  2. begin
  3.   result := nombre + ' tiene ' + inttostr(patas) + ' patas y es de raza ' + Raza;
  4. end;



8. Agregamos mas código a nuestro evento del Botón



delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Mamifero: TMamifero;
  4.   Perro: TPerro;
  5. begin
  6.  
  7.   //Clase base
  8.   Mamifero := TMamifero.Create;
  9.   with Mamifero do begin
  10.     Nombre := 'Perro';
  11.     Patas := 4;
  12.     Memo1.Lines.Add(MuestraDatos);
  13.   end;
  14.  
  15.   //Clase derivada
  16.   Perro := TPerro.Create;
  17.   with Perro do begin
  18.     Nombre := 'Bobby';
  19.     Patas := 4;
  20.     Raza := 'Chihuahua';
  21.     Memo1.Lines.Add(MuestraDatos);
  22.   end;
  23. end;



Ejecutamos el programa y veremos la diferencia entre las dos funciones declaradas.

8. Podemos notar que las dos funciones MuestraDatos son realmente similares, pero aquí es donde vamos a ver los beneficios de la herencia de clases.

Reescribimos el código de la función de la clase derivada MuestraDatos de esta forma:



delphi
  1. function TPerro.MuestraDatos: string;
  2. begin
  3.   result := inherited MuestraDatos + ' y es de raza ' + Raza;
  4. end;



Agregamos la palabra reservada inherited para heredar el comportamiento de la función MuestraDatos de la clase base dentro de la función de la clase derivada, ejecutamos el programa y vean el resultado.

Con esto terminamos este tutorial, esperando que sea de utilidad.

Salud OS
  • 1

#3 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 17 diciembre 2008 - 05:57

Aquí el código completo de nuestro ejemplo.



delphi
  1. Unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, StdCtrls;
  8.  
  9. type
  10.   TMamifero = class(TObject)
  11.     Nombre: string;
  12.     Patas: integer;
  13.     function MuestraDatos:string; virtual;
  14.   end;
  15.  
  16.   TPerro = class(TMamifero)
  17.     Raza: string;
  18.     function MuestraDatos:string; override;
  19.   end;
  20.  
  21.   TForm1 = class(TForm)
  22.     Memo1: TMemo;
  23.     Button1: TButton;
  24.     procedure Button1Click(Sender: TObject);
  25.   private
  26.     { Private declarations }
  27.   public
  28.     { Public declarations }
  29.   end;
  30.  
  31. var
  32.   Form1: TForm1;
  33.  
  34. implementation
  35.  
  36. {$R *.dfm}
  37.  
  38. { TMamifero }
  39.  
  40. function TMamifero.MuestraDatos: string;
  41. begin
  42.   result := nombre + ' tiene ' + inttostr(patas) + ' patas';
  43. end;
  44.  
  45. procedure TForm1.Button1Click(Sender: TObject);
  46. var
  47.   Mamifero: TMamifero;
  48.   Perro: TPerro;
  49. begin
  50.   Mamifero := TMamifero.Create;
  51.   with Mamifero do begin
  52.     Nombre := 'Perro';
  53.     Patas := 4;
  54.     Memo1.Lines.Add(MuestraDatos);
  55.   end;
  56.  
  57.   Perro := TPerro.Create;
  58.   with Perro do begin
  59.     Nombre := 'Bobby';
  60.     Patas := 4;
  61.     Raza := 'Chihuahua';
  62.     Memo1.Lines.Add(MuestraDatos);
  63.   end;
  64. end;
  65.  
  66. { TPerro }
  67.  
  68. function TPerro.MuestraDatos: string;
  69. begin
  70.   result := inherited MuestraDatos + ' y es de raza ' + Raza;
  71. end;
  72.  
  73. end.



Salud OS
  • 2

#4 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 17 diciembre 2008 - 10:02

Hola Egostar,
Disculpa que este post arruine un poquito el tutorial.
Me he quedado sorprendido por la simpleza de tus palabras para explicar el tema sin demasiado tecnicismos.

Si es que no estoy obrando mal, me preguntaba si es posible complementar el tema con una pequeña explicación de la diferencia entre virtual y abstract.

Cuando uno desea, o mejor dicho tiene pensando diseñar, contar con un método que pueda ser sobreescrito en una clase base necesita declarar al método como "virtual". Pero además de virtual, existe otra clásula: abstract.
Cuando uno declara un método virtual abre la posibilidad de que las clases que heredan de la base, puedan modificar e implementar su propio "código" dentro del método. Una clase heredera (o hija) puede o no sobreescribirlo.
El compilador solito se encarga de invocar al método de la clase base o hija según sea necesario.

Por ejemplo, siguiendo tus demostraciones:



delphi
  1. type
  2. TGato = class(TMamifero)
  3. public
  4.   Largobigotes: integer;
  5.   Maullar;
  6. end;



En TGato no implemento la función MostrarDatos. Por tanto cuando haga algo como:



delphi
  1. var Gato: TGato;
  2. begin
  3.   Gato := TGato.Create;
  4.   Gato.Nombre := 'Garfield';
  5.   Gato.Patas := 4;
  6.   Gato.MostrarDatos;
  7. end;



Se ejecutará el MostrarDatos de la clase TMamifero.
Pero si uso el TPerro, observaremos que se llama al MostrarDatos de TPerro.

Ahora, Abstract es algo similar. No está demás decir que para que un método sea abstracto necesariamente debe ser virtual. ¿Qué hace abstract?
En pocas obliga a que sean las clases hijas las que implementen el algoritmo del método. Por tanto no se da ninguna implementación en la clase base.

En resumen:
Virtual se emplea cuando el método pueda ser sobreescrito por el de una clase hija.
Abstracto se emplea cuando se busca que el método sea obligadamente implementado por la clase hija.

Por ejemplo, podríamos hacer algo así:



delphi
  1. TMamifero = class(TObject)
  2. ...
  3. public
  4.   procedure Hablar; virtual; abstract;
  5. end;
  6.  
  7. TPerro = class(TMamifero)
  8. ...
  9. public
  10.   procedure Hablar; override;
  11. end;
  12.  
  13. TGato = class(TMamifero)
  14. ...
  15. public
  16.   procedure Hablar; override;
  17. end;
  18.  
  19. ...
  20.  
  21. procedure TPerro.Hablar;
  22. begin
  23.   ShowMessage('Guau');
  24. end;
  25.  
  26. procedure TGato.Hablar;
  27. begin
  28.   ShowMessage('Miau');
  29. end;



Si se intenta implementar el método Hablar a TMamifero el compilador nos advierte de que es abstracto.

No está demás decir que en las clases hijas se debe incluir la clásula override.
Espero no ser inoportuno con este post. Me pareció que puede contribuir a comprender los conceptos complementarios en el tema de herencia.

Saludos,
  • 2

#5 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 17 diciembre 2008 - 10:47

Gracias amigo Delphius,

Los miembros Public, Private, Protected, Published y Property los queria abordar en tutoriales futuros, sin embargo me parece excelente que hayas enriquecido este tutorial con tu aportación. ;)

Salud OS

Animate a publicar algún tutorial en este tu foro. :)


  • 0

#6 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 17 diciembre 2008 - 11:05

Hola

Revisando el ejemplo he encontrado una omisión grave de mi parte. No estoy liberando los objetos creados. Lo siento :$



delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Mamifero: TMamifero;
  4.   Perro: TPerro;
  5. begin
  6.   Mamifero := TMamifero.Create;
  7.   with Mamifero do begin
  8.     Nombre := 'Perro';
  9.     Patas := 4;
  10.     Memo1.Lines.Add(MuestraDatos);
  11.     Free; //Liberamos el objeto ***********
  12.   end;
  13.  
  14.   Perro := TPerro.Create;
  15.   with Perro do begin
  16.     Nombre := 'Bobby';
  17.     Patas := 4;
  18.     Raza := 'Chihuahua';
  19.     Memo1.Lines.Add(MuestraDatos);
  20.     Free; //Liberamos el objeto ***********
  21.   end;
  22. end;



Salud OS


  • 1

#7 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 diciembre 2008 - 11:37

Gracias amigo Delphius,

Los miembros Public, Private, Protected, Published y Property los queria abordar en tutoriales futuros, sin embargo me parece excelente que hayas enriquecido este tutorial con tu aportación. ;)

Salud OS

Animate a publicar algún tutorial en este tu foro. :)


OK, entonces evito dar indicaciones de visibilidad por el momento ;).
Bueno, ya que me invitas a hablar de algo, quisiera aprovechar este sub-foro de Manuales y Tutoriales para tratar en forma un poco más completa lo que es polimorfismo. :)
Espero que no salga tan técnico. :p

Saludos,
  • 1

#8 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 18 diciembre 2008 - 11:54

OK, entonces evito dar indicaciones de visibilidad por el momento ;).
Bueno, ya que me invitas a hablar de algo, quisiera aprovechar este sub-foro de Manuales y Tutoriales para tratar en forma un poco más completa lo que es polimorfismo. :)


Me parece muy bien amigo, mi intención era comenzar con Herencia, seguir con Polimorfismo y despues con la visibilidad de miembros :D

Espero que no salga tan técnico. :p


Bueno amigo, la verdad es que seria muy bueno que no fuera tan técnico (pero no tan simple como yo lo hago :$) la idea es que aprendamos divirtiendonos y la teoria pues es algo engorrosa a veces, bueno, eso desde mi (paranoico) punto de vista ;)

Salud OS

  • 1

#9 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 19 diciembre 2008 - 09:11

Amigo, excelente Tutorial, estoy aprendiendo :D.

Saludos.
  • 1

#10 Ramsay

Ramsay

    Newbie

  • Miembros
  • Pip
  • 3 mensajes

Escrito 22 julio 2016 - 08:05

Hola , ¿ no conocen un ejemplo sobre como hacer esto en units por separado me refiero a mamifero y perro en unit diferentes como se hace en Visual ?.


  • 1

#11 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 22 julio 2016 - 08:41

Hola , ¿ no conocen un ejemplo sobre como hacer esto en units por separado me refiero a mamifero y perro en unit diferentes como se hace en Visual ?.

 

No hace falta un ejemplo. Basta con que crees una unit para cada clase y referencies la unidad en donde se encuentre la clase base en la sección uses.

Para el ejemplo que se expone aquí digamos que tienes una unidad UMamifero y UPerro, en cada unidad se va a definir su respectiva clase. Ahora, para que TPerro pueda heredad de TMamifero debemos poner en la sección uses de UPerro la UMamifero:


delphi
  1. Unit UPerro;
  2.  
  3. interface
  4.  
  5. uses UMamifero;
  6.  
  7. type
  8. TPerro = class(TMamifero)
  9. // aquí ponemos lo que tiene que tener TPerro
  10. end;
  11.  
  12. implementation
  13. ...

Por cierto, te agradecería que en lo posible se evite exponer dudas en los hilos que sean Manuales y/o Tutoriales.

Si la duda es sobre alguno de ellos, en su lugar consideramos oportuno iniciar un propio hilo en el foro más apropiado al caso y allí hacer referencia al manual o tutorial sobre el cual se tienen dudas o problemas.

 

Muchas gracias.

 

Saludos,

 

Saludos,


  • 1




IP.Board spam blocked by CleanTalk.