PDA

Ver la Versión Completa : Duda con la herencia


oscjae
11-04-2015, 13:55:26
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:


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


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
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:

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/Composition_over_inheritance

http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance

http://programmers.stackexchange.com/questions/65179/where-does-this-concept-of-favor-composition-over-inheritance-come-from

Este comentario creo que explica de forma simple el punto:

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:


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. ;)

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,


...Duda con la herencia...

:rolleyes:

Revisa esta información:

1- La cara oculta de Delphi 4 (Capitulo 7) (http://terawiki.clubdelphi.com/Delphi/Manuales/?download=La_Cara_Oculta_De_Delphi_4_pdf_.zip)

2- Object Oriented Programming in Delphi (https://app.box.com/s/vfbsfdnv9xmv9l24qdlp)

3- Implementando interfaces en Delphi (I) (http://delphiallimite.blogspot.com/2007/10/implementando-interfaces-en-delphi-i.html)

4- Implementando interfaces en Delphi (II) (http://delphiallimite.blogspot.com/2007/10/implementando-interfaces-en-delphi-ii.html)

5- Implementando interfaces en Delphi (y III) (http://delphiallimite.blogspot.com/2007/10/implementando-interfaces-en-delphi-y.html)
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
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/6187018/abstract-class-in-delphi

Al González
14-04-2015, 20:04:54
Aquí hay una falta mía:
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
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!!!