Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Duda con la herencia (https://www.clubdelphi.com/foros/showthread.php?t=88094)

oscjae 11-04-2015 13:55:26

Duda con la herencia
 
Hola a todos, me ha surgido un "problema" que realmente no se si tiene la solución que a mi me gustaría.

Tengo una aplicación con dos formularios padre, y el resto heredan de estos dos, ahora tengo que llamar a un procedimiento determinado (Privilegios) desde todos los formularios, y para no tener que hacerlo en todos los formularios debería hacerlo en el formulario padre, como seria lo normal, pero esos formularios padre son genéricos, los uso para todas mis aplicaciones, y esa procedimiento Privilegios no sera el mismo para un aplicación que para otra, la idea es algo así como crear un procedimiento vacío en los formularios padre, y hacer que apunten a un procedimiento determinado ya en la aplicación, de ese modo puedo hacer que en un aplicación ese procedimiento tenga un implementación diferente a otra aplicación.

No se si me he explicado, espero puedan ayudarme.
Gracias.

Al González 11-04-2015 18:35:18

Haría falta conocer más detalles sobre tu(s) proyecto(s), pero de entrada pareciera que podría resolverse con métodos virtuales.

Quizá convenga que esos dos formularios "base" tengan un padre común, en el cual declarar el método en cuestión como Virtual; Abstract;. Entonces en cada formulario derivado del formulario base redefinir (Override;) ese método según la implementación concreta que deba tener ahí.

De cualquier forma, puede ayudar que nos muestres un poco más de lo que estás haciendo.

Un saludo.

Al González.

AgustinOrtu 11-04-2015 19:42:58

Podes hacerlo como comenta Al, que seria lo correcto y mas recomendable.

En el Form padre:

Código Delphi [-]
  procedure Privilegios; virtual; abstract;

La directiva virual permite que una clase que descienda del padre, pueda sobreescribir el metodo en cuestion, usando la directiva override

Por otro lado la directiva abstract sirve para que la clase en cuestion no deba implementar el metodo. Simplemente esta para "acordarse" de que los hijos deben implementarlo. Un ejemplo seria

Código Delphi [-]
interface

type

  TFormHijo = class(TFormPadre)
  private
    procedure Privilegios; override;
  end;

implementation

{ TFormHijo }

procedure TFormHijo.Privilegios
begin

end;

Si TFormHijo no declara y/o no provee una implementacion para el metodo Privilegios, el programa no compila

Aunque tambien simplemente en cada uno de tus proyectos declaras e implementas el metodo Privilegios y listo, aunque no estarias aprovechando todas las ventajas de la OO.

Saludos

Al González 11-04-2015 20:29:16

Sólo un par de matices.

Se aconseja usar la palabra sobreescribir para overwrite. Mientras que es más apropiado decir redefinir para override, cuando se habla de métodos virtuales.

Y respecto a
Cita:

Empezado por AgustinOrtu (Mensaje 491167)
Si TFormHijo no declara y/o no provee una implementacion para el metodo Privilegios, el programa no compila

En realidad sí compila, pero la aplicación elevará una excepción si se intenta llamar al método abstracto.

Saludos. :)

AgustinOrtu 11-04-2015 21:11:38

Interesante Al gracias por las aclaraciones!

Yo pensaba que si no se redefinia el metodo en la clase hija, el compilador lanzaria un error de "Unsatisfied forward or external declaration" que es lo que sucede cuando te falta implementar un metodo declarado (por ejemplo)

EDITO: Sere curioso.. existe algun mecanismo para asegurar que la clase hija implemente todos los metodos abstractos, impidiendo la compilacion si faltase alguno?

mamcx 11-04-2015 22:15:06

La explicación de AL es la forma normal cuando se tiene una jerarquia de clases, pero viendo este punto:

Cita:

Empezado por oscjae (Mensaje 491158)
de ese modo puedo hacer que en un aplicación ese procedimiento tenga un implementación diferente a otra aplicación.

Puede que te deje corto. El problema de la OO es que la herencia es "vertical" y no "horizontal". Osea, la OO es un "arbol" con un "raiz" y es facil compartir código al caminar rama y sub-ramas, de arriba a abajo, pero no al saltar de una rama a la siguiente (de lado a lado) sin obligar "subir" mas arriba hasta un ancestro comun a todas ellas... y aun así puede que eso no sea suficiente o posible.

Hay un principio de la OO que es muy util: Composición en vez de herencia. 9 de 10 veces, es MEJOR:

https://en.wikipedia.org/wiki/Compos...er_inheritance

http://stackoverflow.com/questions/4...er-inheritance

http://programmers.stackexchange.com...ance-come-from

Este comentario creo que explica de forma simple el punto:

Cita:

Inheritance is primarily a polymorphic tool, but some people, much to their later peril, attempt to use it as a way of reusing/sharing code
Composición permite compartir tanto "vertical" como "horizontal" e incluso, a travez de multiples arboles con diferentes "raices" o que saltan de árbol a árbol, aplicación a aplicación, e incluso, de lenguaje a lenguaje!

Un ejemplo puede ser:

Código Delphi [-]
type
    IPrivilegios = Interface(IInterface)
     // Retornar una lista de privilegios, con nombre= Acceso si/no
      function ListarPrivilegios(para:TForm):TDictionary<string, Boolean>;
    end;

De alli puede hacer 2 cosas:

1- Puedes implementar la interface en formularios, y NO IMPORTAN SI HEREDAN DEL MISMO BASE

o

2- Puedes usar una simple funcion, sin amarrar a formularios:

Porque pasas a la intefaces el formulario de forma explicita, en vez de de depender que estas dentro de la clases. Asi incluso se lo puedes aplicar a formularios externos a tu codigo.

3- E incluso, si en vez de forzar que privilegios tiene que ver con formularios, cambias el parametro "para" con una clase "Generics" u otra interface, puedes aplicarselo a cualquier objeto (ej: Obtener los privilegios para un usuario, un archivo, etc)

Al González 12-04-2015 03:15:37

Buena exposición, Mario. Ojalá oscjae explique su problema un poco más, para que podamos ver si necesita una inyección de adrenalina en el corazón o sólo tomar un par de aspirinas. ;)

Cita:

Empezado por AgustinOrtu (Mensaje 491173)
EDITO: Seré curioso...¿existe algún mecanismo para asegurar que la clase hija implemente todos los métodos abstractos, impidiendo la compilación si faltase alguno?

La curiosidad es el mejor imán de conocimiento. ^\||/

¿Cómo controlarías eso al compilar una biblioteca de la cual deseas que otros deriven? O, en un caso distinto, ¿deberá el compilador revisar todas las clases directa e indirectamente descendientes para verificar que no haya quedado ningún método abstracto sin implementar? ¿O qué pasa si algún maestro de las VMTs decide crear clases hijas en tiempo de ejecución? En fin, puedes marcar un método o una clase como Abstract, pero quizá es mejor no pedirle al compilador que haga labores de auditoría en demasía. Ya hace bastante advirtiéndonos sobre muchos probables códigos malos.

En todo caso, debemos comprometernos con nosotros mismos a no poner en producción ninguna aplicación que al compilarse haya arrojado algún warning.

Saludos compilatorios. :)

Al.

nlsgarcia 12-04-2015 05:28:26

oscjae,

Cita:

Empezado por oscjae
...Duda con la herencia...

:rolleyes:

Revisa esta información:
Espero sea útil :)

Nelson.

AgustinOrtu 12-04-2015 05:48:50

Hola Al, nuevamente gracias por tu comentario

Evidentemente se nota que nunca he diseñado una jerarquia lo bastante grande, aun no salgo del "meto todo mi codigo en el ejecutable y se lo doy a quien lo ocupe", (ya llegara el dia en el que permitire que alguien pueda extender mis "grandes creaciones" :)) ni hablar como la que propone mamcx, donde si le agregamos interfaces al asunto el universo puede volverse bastante grande :)

Espero que no me lleve algun dia la sorpresa de un Abstract Error, ya que todo este tiempo me creia que si sale por Code Insight y compila, pues que problema puede haber :D

Pero ahora fuera bromas, habrá que prestar mayor atencion a los warning, leer la documentacion e implementacion de las cosas y no ir tan a saco

Saludos

mamcx 12-04-2015 18:44:54

Cita:

Empezado por AgustinOrtu (Mensaje 491173)
EDITO: Sere curioso.. existe algun mecanismo para asegurar que la clase hija implemente todos los metodos abstractos, impidiendo la compilacion si faltase alguno?

Existe:

http://stackoverflow.com/questions/6...lass-in-delphi

Al González 14-04-2015 20:04:54

Aquí hay una falta mía:
Cita:

Empezado por Al González (Mensaje 491170)
Se aconseja usar la palabra sobreescribir para overwrite. Mientras que es más apropiado decir redefinir para override, cuando se habla de métodos virtuales.

Sobrescribir lleva una sola e. :o :)

Casimiro Notevi 14-04-2015 20:11:32

Cita:

Empezado por Al González (Mensaje 491300)
Sobrescribir lleva una sola e.

Mejor que sobre y no que falte :p

oscjae 29-04-2015 08:56:49

Perdonad porque no he podido responder antes, ya esta solucionado gracias a vosotros.
Saludos!!!


La franja horaria es GMT +2. Ahora son las 12:09:56.

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