sobre herencia multiple

11/04/2005 - 19:58 por olopeich | Informe spam
Epa!

Tengo un problema q no se como enfocar; es mas bien teorico, ahi va:

Tengo una aplicacion con clientes, cada cliente es un objeto con sus
propiedades metodos y tal.

En un momento dado tengo q representar esos clientes con un treeview. Lo
que hago es derivar una clase de TreeNode llamada mTreeNode donde añado
las propiedades que me interesan de la clase clientes; de este modo
cuando hago click en un nodo del arbol tengo acceso a todos los datos de
ese cliente, q visualizo o manipulo con ayuda de otros controles. Hasta
aqui vamos bien... o mejor dicho medio bien porque al no tener herencia
multiple (es la unica manera q se me ocurre de resolver el problema) no
puedo hacer un

class mTreenode
inherits Treenode, Clientes

.
.
.

End class

porque evidentemente mTreeNode tiene q heredar de Treenode, sino el
treeview peta. De esta guisa tengo q duplicar todo el codigo de clientes
en la clase mTreeView q me interese en vez de simplemente heredar.

Si mas adelante tengo otra representacion distinta de Cliente (yo q se,
con listbox por ejemplo) tengo q volver a hacer lo mismo: crear otra
clase que herede del tipo de dato que ese control pida y duplicar todo
el codigo de Cliente en esa clase.

Y digo yo: hay alguna manera mas elegante de resolver esto en vb .net???
me da la impresion de estar obviando algo muy basico pero no atino...

Saludos y mil gracias a todos.

Preguntas similare

Leer las respuestas

#1 Tristan
11/04/2005 - 21:33 | Informe spam
Bueno, en general la herencia múltiple no suele ser muy recomendable. Además
de los problemas que genera, en tu caso no vería mucho sentido en que un
objeto sea a la vez Cliente y TreeNode. Demasiado diferentes. Yo más bien
diria que tienes un objeto cliente que SE REPRESENTA mediante un TreeNode.
Es decir, tu objeto contiene, referencia, un objeto treenode.

Es decir, tu cliente puede crear en su constructor, o cuando sea necesario,
un objeto TreeNode, y puede visualizarlo dentro de un TreeView asociado.

Pero incluso este caso, estaría en contra de un diseño correcto en tres
capas, puesto que estarías uniendo capa de negocio y de interface en un
mismo objeto. Todo depende de que quieras seguir esas reglas de diseño. Pero
aplicando herencia múltiple aún sería mayor la infracción.

Por otro lado, no olvides que aunque .net no admite herencia múltiple de
implementación, si admite herencia múltiple de interface. Tu objeto puede
heredar de TreeNode e implementar la interface que necesite de Cliente.

Para mi, la mejor solución es o bien la que te dije al principio, o incluso
un diseño en que se separe negocio e interface. Una clase para
representación visual del cliente (heredada de TreeNode) y otra con las
reglas del cliente, que herede de la clase que necesites, tal vez Persona.

Juan Carlos Badiola
MVP - C#
Respuesta Responder a este mensaje
#2 George Muniz
11/04/2005 - 22:15 | Informe spam
Que tal.

Tristan. Tu solución me parece buena, solo que creo que lo
estas haciendo al revés, a mi parecer se deberia hacer lo
siguiente.

Crear una clase que herede de TreeNode, dentro de esa
clase heredada crear una referencia hacia cliente
(propiedad) que por ejemplo se la puede asignar en el
constructor de tu clase heredada, asi creo que no estarias
mezclando la capa de negocios con la interfaz de usuario.

Saludos.
George Muñiz (MCP Vb.Net)


Bueno, en general la herencia múltiple no suele ser muy


recomendable. Además
de los problemas que genera, en tu caso no vería mucho


sentido en que un
objeto sea a la vez Cliente y TreeNode. Demasiado


diferentes. Yo más bien
diria que tienes un objeto cliente que SE REPRESENTA


mediante un TreeNode.
Es decir, tu objeto contiene, referencia, un objeto


treenode.

Es decir, tu cliente puede crear en su constructor, o


cuando sea necesario,
un objeto TreeNode, y puede visualizarlo dentro de un


TreeView asociado.

Pero incluso este caso, estaría en contra de un diseño


correcto en tres
capas, puesto que estarías uniendo capa de negocio y de


interface en un
mismo objeto. Todo depende de que quieras seguir esas


reglas de diseño. Pero
aplicando herencia múltiple aún sería mayor la infracción.

Por otro lado, no olvides que aunque .net no admite


herencia múltiple de
implementación, si admite herencia múltiple de interface.


Tu objeto puede
heredar de TreeNode e implementar la interface que


necesite de Cliente.

Para mi, la mejor solución es o bien la que te dije al


principio, o incluso
un diseño en que se separe negocio e interface. Una clase


para
representación visual del cliente (heredada de TreeNode)


y otra con las
reglas del cliente, que herede de la clase que necesites,


tal vez Persona.

Juan Carlos Badiola
MVP - C#


.

Respuesta Responder a este mensaje
#3 Tristan
11/04/2005 - 23:05 | Informe spam
Bueno, la verdad es que en algún momento las capas tienen que mezclarse, y
no estoy muy seguro de que de esa otra forma se mezclen menos, pero es
posible que tenga varias ventajas tu diseño.

Yo suelo hacer las cosas separando totalmente las dos clases, pero no me
parece mala idea tu diseño, no.

Juan Carlos Badiola
MVP - C#
Respuesta Responder a este mensaje
#4 olopeich
12/04/2005 - 09:05 | Informe spam
muchas gracias por responder Tristan. Te comento entre lineas. Adelanto
q soy muy inexperto en estos temas. Llevo progrando muchos años pero
pertenezco a la vieja escuela de la programacion estructurada

Bueno, en general la herencia múltiple no suele ser muy recomendable. Además
de los problemas que genera, en tu caso no vería mucho sentido en que un
objeto sea a la vez Cliente y TreeNode. Demasiado diferentes. Yo más bien
diria que tienes un objeto cliente que SE REPRESENTA mediante un TreeNode.
Es decir, tu objeto contiene, referencia, un objeto treenode.



mmmm, si, esa seria la idea... pero no veo la manera de implementarlo.
Que hago, en mi clase cliente añado una propiedad de tipo treenode? no
se como voy a poder usar todo esto a la hora de componer el treeview. Y
luego esta el caso de q si tengo varias representaciones de un mismo
cliente a lo largo de la aplicacion, lease, un treeview, un listview, un
combobox... que tendria q hacer, dentro de la clase cliente añadir
referencias a todos los controles (o tipos de dato q esperen esos
controles) q vaya a utilizar?

Es decir, tu cliente puede crear en su constructor, o cuando sea necesario,
un objeto TreeNode, y puede visualizarlo dentro de un TreeView asociado.



podrias explicarme un poco la forma de hacer esto? Yo este tipo de
esquema lo utilizo en el siguiente escenario: tengo un treeview con
nodos q son clientes, hago click en uno de ellos y se me devuelve una
clase derivada de treenode q contiene ademas de la info basica del
treenode toda la info del cliente en este caso. Pero no veo como hacer
eso mismo añadiendo una referencia a un treenode desde mi clase cliente...

Y ademas, no estamos en este caso mezclando cosas? quiero decir,
prefiero mantener mi clase cliente limpia de codigo relativo al
interface y derivar una nueva ya 'sucia'... de este modo la clase
original cliente queda impoluta.

Pero incluso este caso, estaría en contra de un diseño correcto en tres
capas, puesto que estarías uniendo capa de negocio y de interface en un
mismo objeto. Todo depende de que quieras seguir esas reglas de diseño. Pero
aplicando herencia múltiple aún sería mayor la infracción.



lo veo, pero sigo sin tener demasiado claro como implementar esto de
forma medio elegante. Ni siquiera se si esta practica es comun. Pero
sino... como debe de hacerse? hacia pensando mantener en memoria un
arraylist equivalente a la representacion del treeview con todos lso
datos q necesito pero no creo q esta sea la manera de implementar.

Aqui me surge otra duda cosmica: el uso del interfaz como simple
'representador' del estado de la aplicacion vs. el interfaz como
representador y contenedor de datos. Yo el treeview a parte de
representar a los datos de la aplicacion lo uso como contenedor... esto
es correcto? a mi me da q no, pero facilita el desarrollo un huevo...

Por otro lado, no olvides que aunque .net no admite herencia múltiple de
implementación, si admite herencia múltiple de interface. Tu objeto puede
heredar de TreeNode e implementar la interface que necesite de Cliente.



bueno, el tema de las interfaces es q nunca lo he entendido. Iba a
preguntarlo en otro hilo pero ya q estamos... :)

Yo lo de las interfaces no veo su utilidad: si digo q el objeto
miTeeeNode implementa las interfaces tal y cual de la clase cliente...
eso quiere decir q me veo obligado a 'rellenar' esas interfaces no?
osea, no hereda el codigo de cliente sino que segun pone en todos los
libros 'es un contrato' por el cual tengo la obligacion de implemementar
(escribir, o en este caso copiar-pegar) el codigo q implemento.

No se si me he explicado.


Para mi, la mejor solución es o bien la que te dije al principio, o incluso
un diseño en que se separe negocio e interface. Una clase para
representación visual del cliente (heredada de TreeNode) y otra con las
reglas del cliente, que herede de la clase que necesites, tal vez Persona.



Esta es la forma en la q lo tengo hecho, pero claro, duplico codigo (las
partes q me interesan de Cliente en miTreeNode) y si cambio las partes
duplicadas en Cliente tengo q cambiar la clase miTreeNode.

Muchas gracias por la ayuda Tristan
Respuesta Responder a este mensaje
#5 Tristan
12/04/2005 - 18:55 | Informe spam
Juan Carlos Badiola
MVP - C#
"olopeich" escribió en el mensaje
news:
muchas gracias por responder Tristan. Te comento entre lineas. Adelanto q
soy muy inexperto en estos temas. Llevo progrando muchos años pero
pertenezco a la vieja escuela de la programacion estructurada



jejejeje, bueno, yo en realidad pertenezco a la escuela de la programación
imperativa. No te imaginas lo que me costón en su dia acostumbrarme a la
programación estructurada, mucho más que el paso a OOP, que en realidad me
pareció natural. Pero se a que te refieres.

Que hago, en mi clase cliente añado una propiedad de tipo treenode? no se
como voy a poder usar todo esto a la hora de componer el treeview. Y luego
esta el caso de q si tengo varias representaciones de un mismo cliente a
lo largo de la aplicacion, lease, un treeview, un listview, un combobox...
que tendria q hacer, dentro de la clase cliente añadir referencias a todos
los controles (o tipos de dato q esperen esos controles) q vaya a
utilizar?



Siguiendo mi diseño, no necesitas una propiedad TreeNode. En principio, el
treenode sería privado al objeto Cliente. Se crearía cuando notifiques al
objeto que tiene que representarse. En ese momento suministrarías un
TreeView, ListView o lo que sea preciso, para que sirva de marco a la
visualización del cliente. El TreeNode, etc... se generará internamente con
la información necesaria y desde la propia clase se asignará como nodo del
TreeView. Espero haberme explicado.

Por el contrario, siguiendo el diseño de George, harías lo contrario. En ese
caso, crearías una clase heredada de TreeNode, otra de ListViewItem, etc...
que tenga una propiedad de tipo Cliente, de ella sacaría los datos la clase
para su representación.

podrias explicarme un poco la forma de hacer esto? Yo este tipo de esquema
lo utilizo en el siguiente escenario: tengo un treeview con nodos q son
clientes, hago click en uno de ellos y se me devuelve una clase derivada
de treenode q contiene ademas de la info basica del treenode toda la info
del cliente en este caso. Pero no veo como hacer eso mismo añadiendo una
referencia a un treenode desde mi clase cliente...



Yo creo que con más razón ahora debes seguir el diseño que te ha propuesto
George. Si tienes objetos derivados de TreeNode, que tienen una propiedad
Cliente, es inmediato tanto obtener los nodos en los que has hecho click,
como obtener de ellos el Cliente asociado. Además, en efecto, quedará todo
más limpio.

Del arraylist que propones no acabo de ver la utilidad.

En cuanto a tu duda cósmica, el interface debe ser en lo posible solo el
representador de datos. Si por ejemplo pasas de un TreeView a un ListView,
cuanto menos lógica de la aplicación hayas puesto unida al interface, más
fácil será el cambio. De hecho, tal vez incluso debas hacer uso de alguna
interface para aislar en lo posible las dos cosas. Por ejemplo algo así como
una interface del tipo IVisualizaCliente podría ser implementado en todas
las clases de interface de usuario que generes. Por poner un ejemplo.

Lo de que no ves claro para que es un interface. Bueno, yo diría que es lo
más útil de la OOP. Sin duda más que la herencia. La utilidad fundamental de
la herencia no es la herencia de código, aunque sea útil, sino el
polimorfismo. Es decir poder utilizar varias clases de forma genérica sin
importar como cada una implementa el método concreto. En este sentido son
tan importantes las interfaces, puesto que de cara al polimorfismo permiten
lo mismo que la herencia.

Yo creo que se ve muy bien la utilidad de las interface pensando en la
sentencia For Each. Un objeto de tipo IEnumerable puede ser recorrido con
For Each. ¿Por qué?. Pues por que (indirectamente) proporciona miembros para
obtener el elemento actual, avanzar al siguiente y posicionarse en el
principio. Gracias a eso, For Each puede obtener la lista completa, sin
preocuparse de si la clase lee los elementos del disco, de un array, de una
pila de tarjetas perforadas, o de lo que sea. Gracias a que For Each se basa
en una interface y no en herencia, el objeto no está obligado a ninguna
jerarquía de clases concreta. Para eso sirve el contrato que has leido en
los libros, para que el compilador sepa que independientemente de como lo
haga, la clase del objeto implementa los miembros necesarios.

En el viejo vb, y todavía en vb.net, muchos hacen polimorfismo sin utilizar
interfaces, mediante late binding. Llamando a miembros que el compilador
desconoce, esperando que el enlace se haga en tiempo de ejecución. Esta es
una pésima forma de trabajo, muy poco eficiente, y sobre todo insegura,
puesto que el compilador no detecta errores. Las interfaces son lo adecuado
para lograr polimorfismo múltiple.

Pufff y tu mensaje es muy largo, poco a poco... :-)
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida