Ir al contenido


Foto

¿Usas interfaces en tus desarrollos habituales?


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

Encuesta: ¿Usas interfaces en tus desarrollos habituales? (17 miembros han emitido voto)

¿Usas interfaces en tus desarrollos habituales?

  1. Si (8 votos [47.06%])

    Porcentaje de voto: 47.06%

  2. No (4 votos [23.53%])

    Porcentaje de voto: 23.53%

  3. Desconozco este recurso (5 votos [29.41%])

    Porcentaje de voto: 29.41%

Votar Los invitados no pueden votar

#1 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 29 septiembre 2010 - 06:44

Saludos.

Al referirme a Interfaz no es a la GUI sino mas bien al recurso para extender la POO.

Cuéntenme sus experiencias con este recurso.

Gracias anticipadas
  • 0

#2 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 29 septiembre 2010 - 07:50

Yo usaba una interface de nombre IImprimible para imprimir con QuickReport el contenido de los dbGrids en aplicaciones MDI. Cuando pude comprar los DevExpress ya no la volví a usar ya que estos vienen con un muy buen motor de impresión.

Saludos
  • 0

#3 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 29 septiembre 2010 - 08:55

Yo usaba una interface de nombre IImprimible para imprimir con QuickReport el contenido de los dbGrids en aplicaciones MDI. Cuando pude comprar los DevExpress ya no la volví a usar ya que estos vienen con un muy buen motor de impresión.

Saludos


Saludos.

Tengo los DevExpress, pero la manera en que imprime su ExpressPrinting System no me convence, lo veo como si fuera un "vago" PrintScreen.

A razón de esto me cree una(s) Clase(s) que me imprime a ReportBuilder tal como se ve el cxGrid (Filtros, Grupos y Orden).  Claro que tiene sus limitaciones:
  • No soporta Imágenes.
  • No soporta Memo (pienso implementarlo).
  • No soporta SubDetalle (pienso implementarlo)

Gracias por tu comentario.

P.D. Dicha rutina la tengo en una primera fase y no esta OO del todo. Eso viene en las nuevas mejoras. (y) ;)
  • 0

#4 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 29 septiembre 2010 - 10:12

Buenas,

Pues la verdad es que no suelo usar interfaces, me gusta mas crear clases normales y dejar aquellos métodos que puedan implementarse como virtual abstract e implementar aquellos que, poco o mucho, puedan tener algo de código.

Incluso muchas veces dejo el método vacío para poder crear objetos de esa clase sin tener que coger uno de sus hijos.

Lo que ha hecho Rolphy Reyes con ReportBuilder lo tengo hecho con QuickReport y con las mismas limitaciones, incluso apaisa la hoja si no cabe en vertical todos los campos :)

Nos leemos

  • 0

#5 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.484 mensajes
  • LocationMallorca

Escrito 29 septiembre 2010 - 10:50

No, nunca he usado interfaces ni me veo usándolas a corto o medio plazo.

No me gustan, para poner eso habría preferido una verdadera implementación de herencia múltiple.

Aunque debo admitir que casi no uso P.O.O., me creo muy pocas clases y lo hago en contadísimas ocasiones. La gran mayoría de mi código es básicamente procedural.

Por cierto, la herencia que uso de forma masiva es la herencia visual de Delphi.

NOTA: Respecto a las QuantumGrids, soy de los vagos que utilizan la impresión incorporada en las DevExpress. :)

Saludos.
  • 0

#6 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 29 septiembre 2010 - 11:18

Habitualmente no.
Pero cuando estuve interiorizándome sobre patrones estuve ojéandolas un poco.

Le reconozco un enorme potencial para situaciones polimórficas y en las que un diseño ya estable y bien organizado se ve perjudicado cuando debe añadirse a una clase algo de esa estructura. En este escenario las interfaces permiten a una clase extenderse sin provocar cambios significativos en el resto de la estructura de modo que no necesita vincularse o formar parte de alguna rama.

En algunos escenarios, podrían ayudar a reducir los casos de clases interpuestas.

En situaciones comunes quizá no se vea mucho uso, pero si se explora la VCL en sus ramas superiores notarán que está llena de interfaces. Es por ello que nos resulta un tanto ajeno el concepto. No es así en otros lenguajes, como Java en donde las interfaces tienen un alto impacto en los desarrollos cotidianos.
La forma en como está diseñada la VCL hace que no independicemos en buena medida del uso de interfaces.

Saludos,
  • 0

#7 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 29 septiembre 2010 - 06:22

No, nunca he usado interfaces ni me veo usándolas a corto o medio plazo.

No me gustan, para poner eso habría preferido una verdadera implementación de herencia múltiple.

Aunque debo admitir que casi no uso P.O.O., me creo muy pocas clases y lo hago en contadísimas ocasiones. La gran mayoría de mi código es básicamente procedural.


Suena mal que no pienses utilizarla, en el sentido del poder que te ofrecen y piensas dejarlo a un lado; aunque como bien mencionas tu código es totalmente estructurado. Ojala y cambies de parecer...

Tengo mis reservas acerca de los lenguajes que soportan herencia múltiple, debo admitir que no he utilizado ninguno de ellos, pero con la documentación existente recalcando una y otra vez la arbitrariedad del código y lo complicado de su implementación prefiero ni siquiera pensar acerca de eso.

Lo interesante de las interfaces es que puedes "enchufar" varias clases, módulos sin muchas complicaciones. Una de las características principales es que cada clase implementa la interfaz a su gusto y tú simplemente debes de invocar el método que tiene la interfaz sin importarte como lo implementaron.

Considero a los desarrolladores de Borland (en su momento) unos genios acerca de como crearon al Delphi en ese aspecto.

Como bien menciona Delphius te da la posibilidad de extender tu clase, sin necesidad de tener que heredar desde otra clase, evitando que el árbol de herencia sea prolongado y a su vez confuso.  Se debe tomar en cuenta ya las Class Helpers aunque eso sea harina de otro costal para su debate.

Por cierto, la herencia que uso de forma masiva es la herencia visual de Delphi.


Genial, de lo primero que conocí como herencia; luego me toco comprender desde el "código".

NOTA: Respecto a las QuantumGrids, soy de los vagos que utilizan la impresión incorporada en las DevExpress. :)


Vamos compañero no dije que usando ese componente uno se convierta en vago, sino que para mí, es un simple PrintScreen de la pantalla salvo que se enfoca en el Grid. Siempre realiza la impresión de manera gráfica (por lo menos es lo que he logrado), sin embargo, imprimiendo desde ReportBuilder se ve de manera "plana".
  • 0

#8 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 29 septiembre 2010 - 06:29

Yo sólo hago clases, nada de interfaces aún.

Salud OS
  • 0

#9 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.484 mensajes
  • LocationMallorca

Escrito 30 septiembre 2010 - 04:01

Hola Rolphy.

Suena mal que no pienses utilizarla, en el sentido del poder que te ofrecen y piensas dejarlo a un lado; aunque como bien mencionas tu código es totalmente estructurado. Ojala y cambies de parecer...


Mi código no lo necesita. Básicamente hago software de gestión, es decir, un montón de formularios de consulta de datos. En mi trabajo diario no necesito herencia múltiple ni interfaces, solo en ocasiones muy puntuales me creo alguna clase, como herramienta a utilizar en los formularios de gestión. Y no creo que cambie de parecer respecto a las interfaces, en esas pocas clases que me creo no voy a utilizar interfaces porque simplemente no me gustan.

Tengo mis reservas acerca de los lenguajes que soportan herencia múltiple, debo admitir que no he utilizado ninguno de ellos, pero con la documentación existente recalcando una y otra vez la arbitrariedad del código y lo complicado de su implementación prefiero ni siquiera pensar acerca de eso.


En mi opinión el mayor problema de la herencia múltiple es la gran repercusión (negativa) que le ha dado la compleja y por tanto confusa implementación que se le ha dado en C++. Pero tenemos muchos ejemplos de implementaciones perfectamente válidas y funcionales de la herencia múltiple, como seria el caso de Eiffel (casualmente también basado en Pascal, como Delphi, y por lo tanto muy fácil de utilizar por nosotros, los pascaleros).

Lo interesante de las interfaces es que puedes "enchufar" varias clases, módulos sin muchas complicaciones. Una de las características principales es que cada clase implementa la interfaz a su gusto y tú simplemente debes de invocar el método que tiene la interfaz sin importarte como lo implementaron.


Yo a eso no lo llamaría característica, sino carencia (o simplemente "gran chapuza").

Lo importante de la herencia es heredar no solo una estructura sino también una implementación. Con las interfaces heredas solo la estructura y tienes que copiar cada vez la implementación (ya que la implementación va a ser la misma en un 99% de los cosas).

Así que al final acabas con un montón de código copiado, con todos los problemas de la época pre-herencia. Es decir, si en un método hay un bug o quieres ampliar u otpimizar cualquier característica, tienes que cambiar el código en todas las clases que implementan esa interface. No basta con corregirlo solo en el método de la interface (como se haría en un buen diseño con herencia múltiple).

¿ Porqué lo llamo "gran chapuza" ?. Porqué simplemente no puedes confiar en ellas. No puedes confiar en que por tener un método heredado de una interface, ese método va a hacer lo que esperas de él. Puesto que ciertamente puede estar bien implementado, pero también puede tener una implementación antigua, con bugs o incompleta, o simplemente puede no tener ninguna implementación en absoluto.

¿ Ejemplos ?. Los Aggregate Fields de los ClientDatasets. Deben implementar una interface TField (o similar), puesto que sus instancias tienen el método .AsFloat. ¿ Pero que ocurre cuando lo llamas ?, obtienes un bonito Access Violation, puesto que el método ni siquiera está implementado. NOTA: No es un caso puntual, me he encontrado bastantes más ejemplos en la VCL. Esto si se hubiera implementado con herencia múltiple, no podría ocurrir.

Considero a los desarrolladores de Borland (en su momento) unos genios acerca de como crearon al Delphi en ese aspecto.



Discrepo contigo, yo los consideraría unos genios si hubiesen hecho una buena implementación de la herencia múltiple.

Lo de las interfaces me parece una chapuza que se vieron obligados a incorporar para soportar las interfaces COM que Microsoft puso masivamente en Windows.

Como bien menciona Delphius te da la posibilidad de extender tu clase, sin necesidad de tener que heredar desde otra clase, evitando que el árbol de herencia sea prolongado y a su vez confuso.  Se debe tomar en cuenta ya las Class Helpers aunque eso sea harina de otro costal para su debate.


No veo ningún problema en los árboles de herencia prolongados. Puesto que van a ser tan prolongados como queramos nosotros.

Saludos.
  • 0

#10 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 30 septiembre 2010 - 06:59

Hola Rolphy.

Mi código no lo necesita. Básicamente hago software de gestión, es decir, un montón de formularios de consulta de datos. En mi trabajo diario no necesito herencia múltiple ni interfaces, solo en ocasiones muy puntuales me creo alguna clase, como herramienta a utilizar en los formularios de gestión. Y no creo que cambie de parecer respecto a las interfaces, en esas pocas clases que me creo no voy a utilizar interfaces porque simplemente no me gustan.

En trabajos habituales como los de gestión y acceso a base de datos como bien indicas, uno poco tiene que vérselas con interfaces y clases.
Aprovechando las posibilidades que ofrece el IDE, se puede conseguir una aplicación casi sin tener que teclear.
Aún así, yo considero que antes proyectos medianos a grandes en lo posible hay que salir un tanto de los planos y las facilidades que nos da un entorno RAD y empezar a estructurar todo siguiendo un adecuado uso de POO, armando clases que se apliquen en la capa de negocio, de datos e incluso en la de interfaz.

En mi opinión el mayor problema de la herencia múltiple es la gran repercusión (negativa) que le ha dado la compleja y por tanto confusa implementación que se le ha dado en C++. Pero tenemos muchos ejemplos de implementaciones perfectamente válidas y funcionales de la herencia múltiple, como seria el caso de Eiffel (casualmente también basado en Pascal, como Delphi, y por lo tanto muy fácil de utilizar por nosotros, los pascaleros).

No he probado Eiffel, aunque he oído hablar de eso. Que está bien logrado su manejo de herencia múltiple.
Yo aún mantengo mis reservas de hasta que punto es bueno y realmente útil la herencia múltiple.

Yo a eso no lo llamaría característica, sino carencia (o simplemente "gran chapuza").

Lo importante de la herencia es heredar no solo una estructura sino también una implementación. Con las interfaces heredas solo la estructura y tienes que copiar cada vez la implementación (ya que la implementación va a ser la misma en un 99% de los cosas).

Es que justo ese es el principio y uso de las interfaces: brinda la estructura, no lleva implementaciones.
Si es necesario estar copiando alguna implementación se debe posiblemente a un error de diseño y de una organización deficiente de las clases a lo largo de las ramas de herencia. O bien, porque se ha tocado fondo a los límites propios del paradigma. En la amplia mayoría de las veces esta segunda opción es el verdadero motivo del problema que tu comentas.

El paradigma OO como cualquier otro, tienes sus cosas buenas y cosas malas. Y uno está en su derecho de utilizarlo, poco, nada, o la medida que uno considere adecuado. E incluso, está en su libertad de llevar su propio modelo.
Pero no por ello se merece descalificar el uso de las interfaces como algo chapuza.
Reconozco que esto es uno de los motivos de porqué se ha propuesto POA: tapar supuestos errores que tiene OO. Pero he aquí que POA no es ni siquiera un nuevo paradigma, más bién es una extensión de POO.
El paradigma OO es por el momento, y lo seguirá siendo por años, lo suficientemente útil y válido para nuestros desarrollos. Por el uso de interfaces no se va a tirar abajo años de estudio (recuerden que la teoría OO data del 67).

Así que al final acabas con un montón de código copiado, con todos los problemas de la época pre-herencia. Es decir, si en un método hay un bug o quieres ampliar u otpimizar cualquier característica, tienes que cambiar el código en todas las clases que implementan esa interface. No basta con corregirlo solo en el método de la interface (como se haría en un buen diseño con herencia múltiple).

¿Podrías explicarlo de nuevo Marc? Creo que no entendí adecuadamente...
Lógicamente si un método X de una interface debe sufrir un cambio, se verán afectadas las declaraciones de dicho método en las clases que la implementan. Nota como dije declaraciones y no implementaciones; puede darse el caso de que su código no se vea perjudicado... si es que se ha llevado un buen diseño.
Si ha de modificarse la implementación en alguna clase, que implemente la interface sus cambios serán locales, a cuanto mucho, a posibles clases descendientes. Si hay otra clase que implementa la misma interface, y no pertenece a la rama de la primera, esta no se ve afectada por los cambios.

¿ Porqué lo llamo "gran chapuza" ?. Porqué simplemente no puedes confiar en ellas. No puedes confiar en que por tener un método heredado de una interface, ese método va a hacer lo que esperas de él. Puesto que ciertamente puede estar bien implementado, pero también puede tener una implementación antigua, con bugs o incompleta, o simplemente puede no tener ninguna implementación en absoluto.

La definición de Interface es justo eso: ella aportan la estructura, más no implementación alguna. Son las clases quienes deben implementarlas. Así está definido el contrato entre una Interface y una Clase.
Si hay una implementación pobre, no es problema de una interface, sino de la clase.
La pobre interface no tiene la culpa, ella solo le ofrece la posibilidad de utilizar los métodos que tiene declaradas.

¿ Ejemplos ?. Los Aggregate Fields de los ClientDatasets. Deben implementar una interface TField (o similar), puesto que sus instancias tienen el método .AsFloat. ¿ Pero que ocurre cuando lo llamas ?, obtienes un bonito Access Violation, puesto que el método ni siquiera está implementado. NOTA: No es un caso puntual, me he encontrado bastantes más ejemplos en la VCL. Esto si se hubiera implementado con herencia múltiple, no podría ocurrir.

Generalmente los métodos que están vacios son porque están declarados virtuales y abstractos y por tanto recae su implementación en las clases descendientes.
¿No será quizá que los Aggregate Fields son un ejemplo más de una clase abstracta y debes hacer uso de una que descienda de ésta?

No he visto aún la la estructura de un TClientDataSet. Habría que ver donde está la falla. Yo no me atrevería a descalificar aún a las interfaces.

Discrepo contigo, yo los consideraría unos genios si hubiesen hecho una buena implementación de la herencia múltiple.

La VCL es un buen logro de ingeniería.
Está comprobado que en una amplia mayoría de los casos, no es útil y necesaria la herencia múltiple. Sólo en los planos más abstractos aparecen posibles casos.

Y si te fijas, es allí donde está el meollo del problema, no en las clases más superficiales de la VCL.
Como dije unos posts antes, si se explora la VCL y se llega a sus profundidades se notan los ejemplos de interfaces.
Las clases que forman parte de las "hojas" del árbol son bastantes estables.

La herencia múltiple por lo general lleva a más problemas que ventajas. Un buen diseño de herencias nos evita el considerar otras medidas.
La gran mayoría de los LOO del mercado son lenguajes que no poseen herencia múltiple de forma natural, JAVA, .NET, PHP, Delphi. El lenguaje OO considerado más puro es Java (y es en estos días el lenguaje líder en el mercado) y a pesar de que en términos puros y abstractos se puede llegar a las palabras de una herencia múltiple éste no posee dicha herencia.

Si el problema del paradigma OO realmente fuera la herencia simple hace tiempo que deberíamos haber saltado del bote y estar trabajando con herencia múltiple o un nuevo paradigma... muy posiblemente basado en los conceptos de POA.
La realidad por otro lado sigue demostrando que el paradigma es más que útil y los suficientemente fuerte como para continuar vigente.

En el momento en que se produzca una llegada generalizada a los límites de la POO se verá la necesidad de discutir si debemos seguir por otro camino.
No se hasta que punto se llegará... por definición el paradigma es extensible por lo que sus límites se pueden expandir más. Debería romperse sus bases y fundamentos como para tirarlo.

Las interfaces están para evitar estos complejos dolores de cabeza y poder brindar soporte de herencia múltiple sin tener que alterar el diseño y el modo en que trabaja el compilador.

El caso de Java es peculiar,... para ser un excelente lenguaje y trabajar con purismos... es muy habitual ver llenar de interfaces sus paquetes. Esto se debe a que se pretendió hacer un C++ sin los semejantes guizados mentales de éste con su manejo múltiple.
Lo que se pretendió de Java es llevar el abstracto a todos los planos... y la realidad del paradigma voltea semejante lógica. Definimos términos abstractos, si... pero en la realidad nos movemos sobre hechos concretos.
La herencia múltiple es redundante en este sentido: doblemente abstracta, y doblemente concreta.

Cosa distinta se ve en Delphi. Las interfaces están lo más alejadas del usuario con lo cual uno puede trabajar cómodamente sin tener que toparse con ellas con demasiada frecuencia.
La VCL es bastante estable, bien pensada. Y trabaja con herencia simple de forma óptima. De ser necesario llegar a términos de múltiple, allí están las interfaces.

No veo ningún problema en los árboles de herencia prolongados. Puesto que van a ser tan prolongados como queramos nosotros.

Efectivamente, tan largo como uno quiera.

Pero en ocasiones no amerita tocar un diseño si ya está estable y no quiere (o no se necesita de más) vincularse clases entre ramas diferentes.
Lo cierto es que se debe mantener un correcto equilibrio en la cantidad de clases, y a su vez en la cantidad de ramas.
Está en uno definir su diseño, a veces está justificado el uso de añadir clases, otras veces se añaden clases pensando en que nos será de utilidad y después con el tiempo vemos que en realidad no nos aporta algo útil... y quizá lo más adecuado hubiera sido optar por considerar el uso de interfaces.

Un ejemplo, muy elegante por cierto, de esto lo he visto en este hilo de CD.

En fin que se trata del en gran ying-yang. Y de él no podemos escapar.

Saludos,
  • 0

#11 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.484 mensajes
  • LocationMallorca

Escrito 30 septiembre 2010 - 10:05

Hola Delphius.

Precisamente en mi opinión Java no es ningún lenguaje excelente. Que sea popular no lo convierte en excelente (en ese caso Basic sería el lenguaje más excelso de la historia). No me gusta Java (al igual que no me gusta ningún lenguaje basado en C, me gusta la legibilidad en el código, y no considero que la sintaxis C ayude en nada a ello), y desde luego no comparto en absoluto que sea el lenguaje OO más puro. ¿ Donde queda entonces Smalltalk ? ¿ y Eiffel ?, .... No sé lo que te ha movido a hacer esa afirmación, pero creo que hay bastantes lenguajes que le pueden disputar con más que sobradas razones a Java el considerarse el lenguaje orientado a objetos más puro.

Dices que tienes reservas sobre las bondades y utilidad de la herencia múltiple. Resulta que yo no tengo ninguna reserva sobre las bondades y utilidad de las interfaces, las considero absolutamente inútiles y un gran paso atrás (gracias de nuevo, Microsoft, por contribuir tanto en el no-avance de las tecnologías de la información).

No entiendo como os puede entusiasmar un mecanismo que simplemente hereda una estructura y nada de implementación. ¿ Que utilidad tiene eso ?, ¿ para hartarse a tener que repetir la misma implementación cada vez que asignas la interface a una nueva clase ?, ¿ para ayudarnos a llenar de bugs nuestras aplicaciones ? (la verdad es que no necesito de esa ayuda artificial, ya me basto y me sobro yo solito para llenar mis programas de bugs :)).

Gracias, pero no, personalmente quiero o bien la verdadera herencia múltiple (bien hecha, y no el desbarajuste implementado en C++) o bien prefiero que nos dejen como estamos, con la herencia simple (con la que ya me considero muy bien servido).

Me niego a crear interfaces. Nunca me he encontrado con ningún caso que las justifique, y desde luego dudo que se pueda encontrar alguno en el que sean más adecuadas que la herencia múltiple.
  • 0

#12 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 30 septiembre 2010 - 10:17

Buenas,

Personalmente uno de los pocos usos que puedo encontrarle a las Interfaces (hoy por hoy) es si se quiere hacer algún sistema de plugins. La verdad es que en este sentido puede facilitar las cosas.

Respecto a la herencia múltiple....... siempre puedes simularla poniendo una property de la clase que necesites tener herencia múltiple.

Nos leemos

  • 0

#13 andres1569

andres1569

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 431 mensajes

Escrito 30 septiembre 2010 - 12:01

No he programado nunca una Interface, pero sí en cambio he tenido que atacar algunas interfaces que trae Delphi para acceder a ciertas características del IDE, básicamente en componentes que necesitan acceder al formulario que se está diseñando (IDesigner). También al atacar hojas de Excel mediante objetos OLE he tenido que "usarlas", que no programarlas.

Es un tema que siempre me ha dado pereza intelectual, y que, como apunta Marc, es algo confuso pues no sabes lo que te vas a encontrar al invocar un método, además no suelen venir bien documentadas (las que he usado, me refiero). Como dice el refrán "llevan el defecto en la virtud": nacieron para ocultar la capa de implementación y en teoría hacer la vida más fácil al programador, como diciendo "tú no tienes que preocuparte de nada más que llamarlas, el resto corre de su cuenta", pero en la práctica, esa pretendida libertad para que cualquier clase se adhiera a una interface para "presentarse en sociedad" como tal, deja al programador final con la incertidumbre de si hará esto o no lo hará, y cómo lo hará. Es decir, parece que con tanto querer ocultar implementación se olvida muchas veces de la documentación o de dejar claro qué requisitos deben cumplir las interfaces derivadas.

Con esto no quiero desacreditarlas, pero sí señalar que se deben programar con mucha cabeza y por favor, bien documentadas.

Saludos
  • 0

#14 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 30 septiembre 2010 - 01:32

Hola,

Marc si me disculpan responderé a tus palabras más adelante.
Ahora debo ausentarme por un rato.

Trataré de explicarme mejor, que por lo que me he releído, algunas cosas no me expliqué bien.

Saludos,
  • 0

#15 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 30 septiembre 2010 - 07:12

Hola,

Disculpen la tardanza, no ando con tiempos.

Bueno, después de releerme, me he dado cuenta de que no supe expresarme adecuadamente.

Hola Delphius.

Precisamente en mi opinión Java no es ningún lenguaje excelente. Que sea popular no lo convierte en excelente (en ese caso Basic sería el lenguaje más excelso de la historia). No me gusta Java (al igual que no me gusta ningún lenguaje basado en C, me gusta la legibilidad en el código, y no considero que la sintaxis C ayude en nada a ello), y desde luego no comparto en absoluto que sea el lenguaje OO más puro. ¿ Donde queda entonces Smalltalk ? ¿ y Eiffel ?, .... No sé lo que te ha movido a hacer esa afirmación, pero creo que hay bastantes lenguajes que le pueden disputar con más que sobradas razones a Java el considerarse el lenguaje orientado a objetos más puro.

Pues amigo, En varios lados he leído que Java se jacta de ser el lenguaje más puro.
Pero he aquí que mi intención no es alabarlo, sino de quitarles algunos laureles que muchos le han puesto.

La intención de mi escrito era de explicar, con cierto sarcasmo, que muy a pesar de ser el lenguaje del momento, potente como dicen, tiene unos guizados conceptuales bastante deprimentes... las interfaces se ven por todos lados. La intención de Java fue de ser un C++ mejor. Y si es puro, purísimo debería tener un adecuado soporte de herencia múltiple y no estar llenado de interfaces a los paquetes...
Se ve que han intentado llevar escenarios de herencia simple y múltiple, casos abstractos y concretos en todos los niveles...

Por ello luego lo comparaba con Delphi, en donde mantiene una buena relación entre el poder de la herencia y el uso de interfaces. En Delphi hay pocos casos en los que un usuario debe usar interfaces. Eso muestra que está bien diseñado.

Dices que tienes reservas sobre las bondades y utilidad de la herencia múltiple. Resulta que yo no tengo ninguna reserva sobre las bondades y utilidad de las interfaces, las considero absolutamente inútiles y un gran paso atrás (gracias de nuevo, Microsoft, por contribuir tanto en el no-avance de las tecnologías de la información).

Así es amigo. Aún me planteo y me pregunto si es tan necesaria y útil la herencia múltiple.
No discuto ciertas aplicaciones prácticas, sino el grado de su utilización.

¿En que porcentaje nos vemos diariamente con el uso de herencia múltiple? Es más una excepción a la norma que algo general. Me parece impráctico rediseñar un compilador para que maneje y opere de forma nativa con herencia múltiple si son algunos puntos aislados en donde el diseño se ve fuertemente afectado por esto.
Es allí que está la interface: poder dotar y extender la herencia.
En un plano extremadamente abstracto y general podríamos inferir que una clase tiene el potencial de heredar el comportamiento y la estructura de muchas clases.
Llendo a lo particular, ¿Que escenarios son los más frecuentes?
En la gran inmensa mayoría de los casos basta el diseño simple para cumplir con los propósitos.
Para hacerlo más gráfico, tomemos al ser animal más polimorfo conocido: el ornitorrinco. ¿Cuántas veces a lo largo de la especies de todos lo animales posibles se han visto o se ven casos como este? Son aislados, ciertas excepciones a la norma, a lo general.

El planteo de la herencia múltiple, en su concepción más abstracta tiene validez, más en lo concreto resulta ser solo una cuestión puntual.

Distinto fuera el caso si las excepciones superaran a la norma. Allí si valdría el esfuerzo adicional de ofrecer un esquema de herencia múltiple. Es más quizá hasta en este escenario sería más viable promover otro paradigma.

No entiendo como os puede entusiasmar un mecanismo que simplemente hereda una estructura y nada de implementación. ¿ Que utilidad tiene eso ?, ¿ para hartarse a tener que repetir la misma implementación cada vez que asignas la interface a una nueva clase ?, ¿ para ayudarnos a llenar de bugs nuestras aplicaciones ? (la verdad es que no necesito de esa ayuda artificial, ya me basto y me sobro yo solito para llenar mis programas de bugs :)).

Amigo por favor, tampoco es para considerar que un entusiasmo me lleve al fanatismo.
Si recuerdas en mi primera interversión, mi respuesta es más un No que un sí.
Poco he utilizado interfaces pero no por ello voy a decantar su posibles usos.
Yo defiendo el uso de interfaces, el poco uso que tenga, pero de allí a negarle sus posibilidades hay diferencia.
Mencioné los dos casos en los que es posible esperar su utilización. No pretendía ni pretendo verle más allá porque es un terreno demasiado abstracto en el cual llega a los límites del paradigma.
Si no se me entiende esas palabras, entonces no se de que otro modo decirlo.

Gracias, pero no, personalmente quiero o bien la verdadera herencia múltiple (bien hecha, y no el desbarajuste implementado en C++) o bien prefiero que nos dejen como estamos, con la herencia simple (con la que ya me considero muy bien servido).

Me niego a crear interfaces. Nunca me he encontrado con ningún caso que las justifique, y desde luego dudo que se pueda encontrar alguno en el que sean más adecuadas que la herencia múltiple.


Puedo aceptar tu postura, espero tu puedas aceptar la mia.
Tengo que admitir que me sorprendido el tonos de tus palabras... que me dejas un sabor demasiado amargo, con una actitud demasiado cortante.

Saludos,
  • 0

#16 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 30 septiembre 2010 - 10:33

Saludos.

Es una lastima que este potente recurso sea tan desconocido y por ende mal interpretado e implementado.

Amigo Marc acepto tu posición y la respeto al 100%, pero considero que utilizar el termino de "Gran Chapuza" para este recurso es algo fuerte. Compañero andres1569 si realizas una mala implementación, obtendrás un resultado erróneo tanto sea con Interfaces como con Clases. 

Lamento que no le vean el potencial a esta característica, pero tratare de mostrarles algunos ejemplos de usabilidad y vean con un poco más de agrado a las interfaces. Aclaro que esto no es nada personal ni mucho menos atacando a nadie en particular.

Si hacemos analogía las Interfaces son como las Clases Abstractas introducidas en Delphi, si no me equivoco a partir del 2005. O anteriormente en versiones antiguas (D7-) podríamos decir que es lo mismo una clase "normal" con métodos abstractos, donde cada heredero debe de implementar los métodos a su antojo ¿Me siguen?.

Analizando lo anterior, aquí también se da el caso que si invocamos un método abstracto de la clase padre desde una clase hija heredera, no sabemos su implementación ni si esta implementada adecuadamente.  De esta manera también se introducen Bugs.

Muestro una situación que se da muy frecuente:


delphi
  1. type
  2.   IMostrarMensaje = interface
  3.     ['{C71A12B4-CBFB-4882-A54B-DF012EC77C84}']
  4.     procedure MostrarMensaje;
  5.   end;
  6.  
  7.   IMostrarDialogo = interface
  8.     ['{0937AF3C-DB17-4B68-8124-5B002E5F6AE9}']
  9.     procedure MostrarDialogo;
  10.   end;
  11.  
  12.   IMostrarInput = interface
  13.     ['{EAF3FF31-2377-4BAC-A3B0-D6A47BD59761}']
  14.     procedure MostrarInput;
  15.   end;
  16.  
  17.   TMostrar = class(TInterfacedObject, IMostrarMensaje, IMostrarDialogo, IMostrarInput)
  18.   public
  19.     procedure MostrarMensaje;
  20.     procedure MostrarDialogo;
  21.     procedure MostrarInput;
  22.   end;



Este sería nuestro modelo "normal" donde implementamos todas nuestras interfaces, de aquí sale dos situaciones:

A) La Buena es que una vez implementado los métodos de las interfaces, los herederos contienen estos métodos desde su padre con su implementación sin mayores problemas como se hace con las clases normales.  Y si declaramos esos métodos virtuales en el padre pues los herederos pueden sobreescribir sus comportamientos. Hasta aquí todo bien.

B) La Mala o las malas, primero es que nuestro código se volvería complejo y difícil de seguir si las
interfaces contuvieran muchos métodos, además de obligar a los herederos a tener todos esos métodos sin "necesidad".  Segundo y es a su vez una gran incógnita para muchos de nosotros; cuando me toque implementar esas interfaces en una nueva Clase y el código de los métodos sean los mismos ¿Tendré entonces que copiar y pegar todo el código?.
Ustedes aprovechando me preguntarían ¿Para qué me sirven esas "famosas" interfaces si tengo que copiar y pegar todo el código nuevamente? Y esto a su vez me podría replicar los Bugs donde ponga (pegue) ese dichoso código, además de sumarle que para corregir esos errores tengo que revisar todos mis fuentes para ver donde implemente tus "famosas" interfaces.

Corto aquí el mensaje para continuar en otro y sea más fácil de seguir.
  • 0

#17 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 30 septiembre 2010 - 10:35

Continuación.

A lo que yo les respondería: Socio, optemos por cambiar la visión de como planteamos la solución:


delphi
  1. type
  2.   //*************
  3.   IMostrarMensaje = interface
  4.     ['{C71A12B4-CBFB-4882-A54B-DF012EC77C84}']
  5.     procedure MostrarMensaje;
  6.   end;
  7.  
  8.   TMostrarMensaje = class(TInterfacedObject, IMostrarMensaje)
  9.     procedure MostrarMensaje;
  10.   end;
  11.   //*************
  12.  
  13.   //*************
  14.   IMostrarDialogo = interface
  15.     ['{0937AF3C-DB17-4B68-8124-5B002E5F6AE9}']
  16.     procedure MostrarDialogo;
  17.   end;
  18.  
  19.   TMostrarDialogo = class(TInterfacedObject, IMostrarDialogo)
  20.     procedure MostrarDialogo;
  21.   end;
  22.   //*************
  23.  
  24.   //*************
  25.   IMostrarInput = interface
  26.     ['{EAF3FF31-2377-4BAC-A3B0-D6A47BD59761}']
  27.     procedure MostrarInput;
  28.   end;
  29.  
  30.   TMostrarInput = class(TInterfacedObject,IMostrarInput)
  31.     procedure MostrarInput;
  32.   end;
  33.   //*************
  34.  
  35.   TMostrar = class(TInterfacedObject, IMostrarMensaje, IMostrarDialogo, IMostrarInput)
  36.   private
  37.     FMostrarMensaje : IMostrarMensaje;
  38.     FMostrarDialogo : IMostrarDialogo;
  39.     FMostrarInput : IMostrarInput;
  40.   public
  41.     Constructor Create;
  42.     property MostrarMensaje : IMostrarMensaje read FMostrarMensaje write FMostrarMensaje implements IMostrarMensaje;
  43.     property MostrarDialogo : IMostrarDialogo read FMostrarDialogo write FMostrarDialogo implements IMostrarDialogo;
  44.     property MostrarInput : IMostrarInput read FMostrarInput write FMostrarInput implements IMostrarInput;
  45.   end;
  46. implementation
  47.  
  48. {$R *.dfm}
  49.  
  50. { TMostrar }
  51.  
  52. constructor TMostrar.Create;
  53. begin
  54.   Inherited Create;
  55.   FMostrarMensaje := TMostrarMensaje.Create;
  56.   FMostrarDialogo := TMostrarDialogo.Create;
  57.   FMostrarInput := TMostrarInput.Create
  58. end;


Como se puede apreciar he creado Clases Independientes (sí, más código....) que implementan una interfaz determinada y luego en la Clase Principal que contiene todas las interfaces he creado propiedades del tipo Interfaz y he hecho uso de la clausula Implements.

Esa clausula es la que me permite la reutilización del código ya implementado y con esto respondo la "famosa" pregunta (que nos vuelve loco): ¿Tengo que copiar y pegar todo el código en una nueva Clase que implemente esas interfaces?.

Esto nos da una flexibilidad enorme, porque si quisiéramos cambiar el comportamiento especifico de algún método solo debemos heredar de la clase en cuestión (la que implemente la interfaz X) sobreescribir su(s) método(s), realizar los ajustes de lugar y listo.

Espero se me haya comprendido y a su vez crearle un buen sentimiento hacia las interfaces.

P.D. Amig@s bajenle un poco el animo al debate que la idea de este post no era para crear problemas sino para compartir conocimientos.

Gracias por su tiempo!
  • 0

#18 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.484 mensajes
  • LocationMallorca

Escrito 01 octubre 2010 - 05:48

Hola Rolphy, la verdad es que no creo que vaya a mudar nunca mis sentimientos respecto a las interfaces. 

Me sentí tremendamente decepcionado cuando fueron introducidas en Delphi. Para un lenguaje que significó lo que significó Delphi (o incluso Pascal) en su momento, resulta frustrante ver como en lugar de implementar la verdadera herencia visual se contentaron con un parche (solo para poder acceder a los objetos COM de Microsoft). Aunque naturalmente, viendo como en 10 años han sido incapaces aún de sacar un compilador de 64 bits, se comprende que Borland/Inprise/Codegear/Embarcadero, a pesar de sus brillante gloria pasada, hoy en día son simplemente incapaces de una remodelación profunda de Pascal para adaptarlo a la herencia múltiple. En estos momentos solo podemos esperar parches en Delphi.

Como enamorado de Pascal y Delphi, acepto perfectamente eso, pero con lo que no puedo tragar es que encima nos quieran vender que el parche es mejor y más deseable que el original.

Si realmente en un momento determinado solo necesitas una interfaz, en herencia múltiple no tienes más que declarar una clase totalmente abstracta. Así pues las interfaces no son más que un pequeño subconjunto de la herencia múltiple, y por consiguiente solo solventan un pequeño subconjunto de los problemas que solventa la herencia múltiple.

Respecto a tu ejemplo, no veo donde están implementados los procedimientos MostrarMensaje, MostrarDialogo, .... Deberías tenerlos en alguna librería de rutinas para poder usar esa misma implementación en otras asignaciones de la interfaz. Sinceramente, para acabar teniendo una librería de rutinas podemos aplicar ese viejo dicho castellano (vuestro refranero popular es de largo lo que más me gusta de vuestra lengua :)) : "para este viaje no hacían falta tamañas alforjas". Y que conste que no tengo nada en contra de las librerías de rutinas, la programación procedural es perfectamente válida aún si se organiza con esmero (incluso mi código la mayoría de las veces parece programado para el buen viejo TurboPascal).

Supongo que puedes ver las ventajas si en tu ejemplo la implementación estuviera incluida en la misma interfaz. Las ventajas que citas al heredar de la clase que implementa la interfaz también las tienes al declarar una nueva clase que la implemente (muy poca utilidad tendrían las interfaces si solo fueran implementadas por una única clase, y el resto de clases heredasen de ella).

En definitiva, como programador tengo bastantes manías, y la aversión a las interfaces es una de ellas. Me molesta que solo nos hayan puesto una solución tan parcial e incompleta. Y dado que no la necesito, me espero a ver si algún día Embarcadero nos da una sorpresa mayúscula e implementa la herencia múltiple, hasta entonces, no lo necesito, no me gusta y no le voy a buscar ninguna utilidad. Finalmente, para quienes dudan de la utilidad de la herencia múltiple solo puedo responderles que si no pueden apreciarla a simple vista, solo tienen que responderse a la pregunta de porqué todo el software interesante, complejo, optimizado, ... está escrito en su inmensa mayoría en C++ (servidores de bases de datos, sistemas operativos, ... incluso los juegos). Si a cualquiera de sus programadores le dices que tiene que renunciar a la herencia múltiple (por enrevesada aunque perfectamente funcional que sea su implementación en C++) te va a perseguir, teclado en ristre, por toda la avenida de La Diagonal.

NOTA: Aunque todo esto no es más que mi opinión, entiendo que en algo tan subjetivo otros podáis tener opiniones diametralmente opuestas.

Saludos.
  • 0

#19 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.484 mensajes
  • LocationMallorca

Escrito 01 octubre 2010 - 06:53

Hola Delphius

La intención de mi escrito era de explicar, con cierto sarcasmo, que muy a pesar de ser el lenguaje del momento, potente como dicen, tiene unos guizados conceptuales bastante deprimentes... las interfaces se ven por todos lados. La intención de Java fue de ser un C++ mejor. Y si es puro, purísimo debería tener un adecuado soporte de herencia múltiple y no estar llenado de interfaces a los paquetes...
Se ve que han intentado llevar escenarios de herencia simple y múltiple, casos abstractos y concretos en todos los niveles...


Smalltalk, el lenguaje fundador de la programación orientada a objetos, y creado desde el primer momento con solo ese paradigma en mente (y no como una evolución tardía de un lenguaje procedural anterior, como C++, Java, Delphi, ...), tampoco tiene herencia múltiple ni interfaces ni nada por el estilo. ¿ Eso quiere significa que las interfaces no son verdadera programación orientada a objetos ?. No lo creo, simplemente cada lenguaje establece las características que le parecen oportunas.

Por ello luego lo comparaba con Delphi, en donde mantiene una buena relación entre el poder de la herencia y el uso de interfaces. En Delphi hay pocos casos en los que un usuario debe usar interfaces. Eso muestra que está bien diseñado.


En este caso creo que la razón es más sencilla. Simplemente la VCL se creó en sus orígenes con herencia simple. Y cuando bastantes años más tarde se añadió el soporte de interfaces a Delphi, esto solo afectó de una forma tangencial a la VCL, que mantuvo su estructura original enfocada en la herencia simple (a diferencia de Java que se programó desde el principio con interfaces, y por lo tanto se refleja en su librería de clases).

Así es amigo. Aún me planteo y me pregunto si es tan necesaria y útil la herencia múltiple.
No discuto ciertas aplicaciones prácticas, sino el grado de su utilización.


Su grado de utilización es masivo. Prácticamente todo el software sensible (complejo, que necesita de una gran optimización, etc. ...) está escrito en C++ (sistemas operativos, gestores de bases de datos, ...), y para sus programadores la herencia múltiple (por enrevesada aunque totalmente funcional que sea la implementación de C++) es irrenunciable.

¿En que porcentaje nos vemos diariamente con el uso de herencia múltiple? Es más una excepción a la norma que algo general. Me parece impráctico rediseñar un compilador para que maneje y opere de forma nativa con herencia múltiple si son algunos puntos aislados en donde el diseño se ve fuertemente afectado por esto.
Es allí que está la interface: poder dotar y extender la herencia.
En un plano extremadamente abstracto y general podríamos inferir que una clase tiene el potencial de heredar el comportamiento y la estructura de muchas clases.
Llendo a lo particular, ¿Que escenarios son los más frecuentes?
En la gran inmensa mayoría de los casos basta el diseño simple para cumplir con los propósitos.
Para hacerlo más gráfico, tomemos al ser animal más polimorfo conocido: el ornitorrinco. ¿Cuántas veces a lo largo de la especies de todos lo animales posibles se han visto o se ven casos como este? Son aislados, ciertas excepciones a la norma, a lo general.

El planteo de la herencia múltiple, en su concepción más abstracta tiene validez, más en lo concreto resulta ser solo una cuestión puntual.

Distinto fuera el caso si las excepciones superaran a la norma. Allí si valdría el esfuerzo adicional de ofrecer un esquema de herencia múltiple. Es más quizá hasta en este escenario sería más viable promover otro paradigma.

...
...

Amigo por favor, tampoco es para considerar que un entusiasmo me lleve al fanatismo.
Si recuerdas en mi primera interversión, mi respuesta es más un No que un sí.
Poco he utilizado interfaces pero no por ello voy a decantar su posibles usos.
Yo defiendo el uso de interfaces, el poco uso que tenga, pero de allí a negarle sus posibilidades hay diferencia.
Mencioné los dos casos en los que es posible esperar su utilización. No pretendía ni pretendo verle más allá porque es un terreno demasiado abstracto en el cual llega a los límites del paradigma.
Si no se me entiende esas palabras, entonces no se de que otro modo decirlo.


¿ Quieres buscarle una utilidad práctica a las interfaces ?, aunque algo alejada a la programación que hacemos la gran mayoría, estoy seguro de que le podemos encontrarle más de una. Pero mi argumentación se basa en el hecho, que creo indiscutible, de que cualquier utilidad que le encuentres a las interfaces, estará al menos igual aunque lo más probable es que mucho mejor solucionado con herencia múltiple (ya que una clase totalmente abstracta es exactamente igual a una interfaz, por lo que las demás características de la herencia múltiple solo pueden sumar a lo máximo que logrará una interfaz). Por eso estoy tan molesto con que una empresa pionera en los compiladores como Borland, en un lenguaje pionero y en su momento incluso revolucionario como Delphi, se contenten con ofrecernos una solución tan incompleta.

Puedo aceptar tu postura, espero tu puedas aceptar la mia.
Tengo que admitir que me sorprendido el tonos de tus palabras... que me dejas un sabor demasiado amargo, con una actitud demasiado cortante.


Lo siento si da esa impresión, ese tono no es para nada contigo, naturalmente que acepto tu posición, ese tono está reservado para las cosas que me molestan, es decir la gente de Borland que implementó las interfaces. Me disgustan las interfaces y me molesta que nos quieran vender como óptima una solución tan parcial e incompleta porque simplemente su incompetencia en compiladores estos últimos años (más que demostrada en la incapacidad de cumplir los Roadmaps y alargar hasta el infinito características que llevan prometiendo desde hace años, como el compilador de 64 bits).

Es por esto que digo que las interfaces son una "chapuza" o inútiles y totalmente innecesarias. No es que sean tan chapuzas o inútiles por si mismas, simplemente lo son al lado del verdadero modelo, la herencia múltiple. Si los programadores de Embarcadero hicieran bien su trabajo e implementaran herencia múltiple en Delphi, no necesitaríamos para nada las interfaces.

Hay momentos en que comprendo demasiado bien a este individuo (aunque preferiría que se cambiase el nombre a Borland/Embarcadero Hater, cosa que se ajusta más a la realidad).

http://delphihaters.blogspot.com/

Saludos.
  • 0

#20 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 01 octubre 2010 - 07:01


Respecto a tu ejemplo, no veo donde están implementados los procedimientos MostrarMensaje, MostrarDialogo, .... Deberías tenerlos en alguna librería de rutinas para poder usar esa misma implementación en otras asignaciones de la interfaz. Sinceramente, para acabar teniendo una librería de rutinas podemos aplicar ese viejo dicho castellano (vuestro refranero popular es de largo lo que más me gusta de vuestra lengua :)) : "para este viaje no hacían falta tamañas alforjas". Y que conste que no tengo nada en contra de las librerías de rutinas, la programación procedural es perfectamente válida aún si se organiza con esmero (incluso mi código la mayoría de las veces parece programado para el buen viejo TurboPascal).

Supongo que puedes ver las ventajas si en tu ejemplo la implementación estuviera incluida en la misma interfaz. Las ventajas que citas al heredar de la clase que implementa la interfaz también las tienes al declarar una nueva clase que la implemente (muy poca utilidad tendrían las interfaces si solo fueran implementadas por una única clase, y el resto de clases heredasen de ella).


Saludos.

Amigo Marc, pensé que no era necesario mostrar el código de la implementación de los métodos.

Corrigiendo esa parte, las clases que implementan cada interfaz por separado lo que podrían contener sería hasta un simple ShowMessage con el nombre del método.

Algo así:


delphi
  1. { TMostrarMensaje }
  2.  
  3. procedure TMostrarMensaje.MostrarMensaje;
  4. begin
  5.   ShowMessage('MostrarMensaje');
  6. end;
  7.  
  8. { TMostrarDialogo }
  9.  
  10. procedure TMostrarDialogo.MostrarDialogo;
  11. begin
  12.   ShowMessage('MostrarDialogo');
  13. end;
  14.  
  15. { TMostrarInput }
  16.  
  17. procedure TMostrarInput.MostrarInput;
  18. begin
  19.   ShowMessage('MostrarInput');
  20. end;



Lo que quiero es que puedan constatar la flexibilidad que nos ofrece.  Puedes perfectamente en cada clase declarar esos métodos virtuales, así para futuras implementaciones de todas las interfaces en una nueva clase  y deseas que algún método en particular se comporte distinto simplemente heredas desde la clase a cambiar, codificas el nuevo comportamiento y lo implementas.  Un ejemplo vale más que mil palabras:


delphi
  1. type
  2.   //*************
  3.   IMostrarMensaje = interface
  4.     ['{C71A12B4-CBFB-4882-A54B-DF012EC77C84}']
  5.     procedure MostrarMensaje;
  6.   end;
  7.  
  8.   TMostrarMensaje = class(TInterfacedObject, IMostrarMensaje)
  9.     procedure MostrarMensaje; virtual;
  10.   end;
  11.  
  12.   TNuevaMostrarMensaje = class(TMostrarMensaje)
  13.     procedure MostrarMensaje; override;
  14.   end;
  15.   //*************
  16.  
  17.   //*************
  18.   IMostrarDialogo = interface
  19.     ['{0937AF3C-DB17-4B68-8124-5B002E5F6AE9}']
  20.     procedure MostrarDialogo;
  21.   end;
  22.  
  23.   TMostrarDialogo = class(TInterfacedObject, IMostrarDialogo)
  24.     procedure MostrarDialogo;
  25.   end;
  26.   //*************
  27.  
  28.   //*************
  29.   IMostrarInput = interface
  30.     ['{EAF3FF31-2377-4BAC-A3B0-D6A47BD59761}']
  31.     procedure MostrarInput;
  32.   end;
  33.  
  34.   TMostrarInput = class(TInterfacedObject,IMostrarInput)
  35.     procedure MostrarInput;
  36.   end;
  37.   //*************
  38.  
  39.   TMostrar = class(TInterfacedObject, IMostrarMensaje, IMostrarDialogo, IMostrarInput)
  40.   private
  41.     FMostrarMensaje : IMostrarMensaje;
  42.     FMostrarDialogo : IMostrarDialogo;
  43.     FMostrarInput : IMostrarInput;
  44.   public
  45.     Constructor Create;
  46.     property MostrarMensaje : IMostrarMensaje read FMostrarMensaje write FMostrarMensaje implements IMostrarMensaje;
  47.     property MostrarDialogo : IMostrarDialogo read FMostrarDialogo write FMostrarDialogo implements IMostrarDialogo;
  48.     property MostrarInput : IMostrarInput read FMostrarInput write FMostrarInput implements IMostrarInput;
  49.   end;
  50.  
  51.   TNuevoMostrar = class(TInterfacedObject, IMostrarMensaje, IMostrarDialogo, IMostrarInput)
  52.   private
  53.     FMostrarMensaje : IMostrarMensaje;
  54.     FMostrarDialogo : IMostrarDialogo;
  55.     FMostrarInput : IMostrarInput;
  56.   public
  57.     Constructor Create;
  58.     property MostrarMensaje : IMostrarMensaje read FMostrarMensaje write FMostrarMensaje implements IMostrarMensaje;
  59.     property MostrarDialogo : IMostrarDialogo read FMostrarDialogo write FMostrarDialogo implements IMostrarDialogo;
  60.     property MostrarInput : IMostrarInput read FMostrarInput write FMostrarInput implements IMostrarInput;
  61.   end;
  62. implementation
  63.  
  64. {$R *.dfm}
  65.  
  66. { TMostrarMensaje }
  67.  
  68. procedure TMostrarMensaje.MostrarMensaje;
  69. begin
  70.   ShowMessage('MostrarMensaje');
  71. end;
  72.  
  73. { TMostrarDialogo }
  74.  
  75. procedure TMostrarDialogo.MostrarDialogo;
  76. begin
  77.   ShowMessage('MostrarDialogo');
  78. end;
  79.  
  80. { TMostrarInput }
  81.  
  82. procedure TMostrarInput.MostrarInput;
  83. begin
  84.   ShowMessage('MostrarInput');
  85. end;
  86.  
  87. { TMostrar }
  88.  
  89. constructor TMostrar.Create;
  90. begin
  91.   Inherited Create;
  92.   FMostrarMensaje := TMostrarMensaje.Create;
  93.   FMostrarDialogo := TMostrarDialogo.Create;
  94.   FMostrarInput := TMostrarInput.Create
  95. end;
  96.  
  97. { TNuevaMostrarMensaje }
  98.  
  99. procedure TNuevaMostrarMensaje.MostrarMensaje;
  100. begin
  101.   inherited;
  102.   ShowMessage('TNuevaMostrarMensaje.MostrarMensaje');
  103. end;
  104.  
  105. { TNuevoMostrar }
  106.  
  107. constructor TNuevoMostrar.Create;
  108. begin
  109.   Inherited Create;
  110.   FMostrarMensaje := TNuevaMostrarMensaje.Create;
  111.   FMostrarDialogo := TMostrarDialogo.Create;
  112.   FMostrarInput := TMostrarInput.Create
  113. end;


Como podrán notar, he creado una clase nueva a partir de TMostrarMensaje llamada TNuevaMostrarMensaje que sobrescribe el método MostrarMensaje y mi nueva clase TNuevoMostrar sigue implementando las interfaces normalmente con el único cambio en el constructor que instancia a TNuevaMostrarMensaje.

Ustedes me podrían decir que sigue mostrando el comportamiento heredado del padre TMostrarMensaje y lo que ustedes buscan es que sea una implementación totalmente nueva, pues les respondo: No hay problemas, eso también se logra.


delphi
  1. type
  2.   //*************
  3.   IMostrarMensaje = interface
  4.     ['{C71A12B4-CBFB-4882-A54B-DF012EC77C84}']
  5.     procedure MostrarMensaje;
  6.   end;
  7.  
  8.   TMostrarMensaje = class(TInterfacedObject, IMostrarMensaje)
  9.     procedure MostrarMensaje; virtual;
  10.   end;
  11.  
  12.   TNuevaMostrarMensaje = class(TMostrarMensaje)
  13.     procedure MostrarMensaje; override;
  14.   end;
  15.  
  16.   TSegundaNuevaMostrarMensaje = class(TInterfacedObject, IMostrarMensaje)
  17.     procedure MostrarMensaje; virtual;
  18.   end;
  19.   //*************
  20.  
  21.   //*************
  22.   IMostrarDialogo = interface
  23.     ['{0937AF3C-DB17-4B68-8124-5B002E5F6AE9}']
  24.     procedure MostrarDialogo;
  25.   end;
  26.  
  27.   TMostrarDialogo = class(TInterfacedObject, IMostrarDialogo)
  28.     procedure MostrarDialogo;
  29.   end;
  30.   //*************
  31.  
  32.   //*************
  33.   IMostrarInput = interface
  34.     ['{EAF3FF31-2377-4BAC-A3B0-D6A47BD59761}']
  35.     procedure MostrarInput;
  36.   end;
  37.  
  38.   TMostrarInput = class(TInterfacedObject,IMostrarInput)
  39.     procedure MostrarInput;
  40.   end;
  41.   //*************
  42.  
  43.   TMostrar = class(TInterfacedObject, IMostrarMensaje, IMostrarDialogo, IMostrarInput)
  44.   private
  45.     FMostrarMensaje : IMostrarMensaje;
  46.     FMostrarDialogo : IMostrarDialogo;
  47.     FMostrarInput : IMostrarInput;
  48.   public
  49.     Constructor Create;
  50.     property MostrarMensaje : IMostrarMensaje read FMostrarMensaje write FMostrarMensaje implements IMostrarMensaje;
  51.     property MostrarDialogo : IMostrarDialogo read FMostrarDialogo write FMostrarDialogo implements IMostrarDialogo;
  52.     property MostrarInput : IMostrarInput read FMostrarInput write FMostrarInput implements IMostrarInput;
  53.   end;
  54.  
  55.   TNuevoMostrar = class(TInterfacedObject, IMostrarMensaje, IMostrarDialogo, IMostrarInput)
  56.   private
  57.     FMostrarMensaje : IMostrarMensaje;
  58.     FMostrarDialogo : IMostrarDialogo;
  59.     FMostrarInput : IMostrarInput;
  60.   public
  61.     Constructor Create;
  62.     property MostrarMensaje : IMostrarMensaje read FMostrarMensaje write FMostrarMensaje implements IMostrarMensaje;
  63.     property MostrarDialogo : IMostrarDialogo read FMostrarDialogo write FMostrarDialogo implements IMostrarDialogo;
  64.     property MostrarInput : IMostrarInput read FMostrarInput write FMostrarInput implements IMostrarInput;
  65.   end;
  66.  
  67.   TSegundaNuevaMostrar = class(TInterfacedObject, IMostrarMensaje, IMostrarDialogo, IMostrarInput)
  68.   private
  69.     FMostrarMensaje : IMostrarMensaje;
  70.     FMostrarDialogo : IMostrarDialogo;
  71.     FMostrarInput : IMostrarInput;
  72.   public
  73.     Constructor Create;
  74.     property MostrarMensaje : IMostrarMensaje read FMostrarMensaje write FMostrarMensaje implements IMostrarMensaje;
  75.     property MostrarDialogo : IMostrarDialogo read FMostrarDialogo write FMostrarDialogo implements IMostrarDialogo;
  76.     property MostrarInput : IMostrarInput read FMostrarInput write FMostrarInput implements IMostrarInput;
  77.   end;
  78.  
  79. implementation
  80.  
  81. {$R *.dfm}
  82.  
  83. { TMostrarMensaje }
  84.  
  85. procedure TMostrarMensaje.MostrarMensaje;
  86. begin
  87.   ShowMessage('MostrarMensaje');
  88. end;
  89.  
  90. { TMostrarDialogo }
  91.  
  92. procedure TMostrarDialogo.MostrarDialogo;
  93. begin
  94.   ShowMessage('MostrarDialogo');
  95. end;
  96.  
  97. { TMostrarInput }
  98.  
  99. procedure TMostrarInput.MostrarInput;
  100. begin
  101.   ShowMessage('MostrarInput');
  102. end;
  103.  
  104. { TMostrar }
  105.  
  106. constructor TMostrar.Create;
  107. begin
  108.   Inherited Create;
  109.   FMostrarMensaje := TMostrarMensaje.Create;
  110.   FMostrarDialogo := TMostrarDialogo.Create;
  111.   FMostrarInput := TMostrarInput.Create
  112. end;
  113.  
  114. { TNuevaMostrarMensaje }
  115.  
  116. procedure TNuevaMostrarMensaje.MostrarMensaje;
  117. begin
  118.   inherited;
  119.   ShowMessage('TNuevaMostrarMensaje.MostrarMensaje');
  120. end;
  121.  
  122. { TNuevoMostrar }
  123.  
  124. constructor TNuevoMostrar.Create;
  125. begin
  126.   Inherited Create;
  127.   FMostrarMensaje := TNuevaMostrarMensaje.Create;
  128.   FMostrarDialogo := TMostrarDialogo.Create;
  129.   FMostrarInput := TMostrarInput.Create
  130. end;
  131.  
  132. { TSegundaNuevaMostrarMensaje }
  133.  
  134. procedure TSegundaNuevaMostrarMensaje.MostrarMensaje;
  135. begin
  136.   ShowMessage('TSegundaNuevaMostrarMensaje.MostrarMensaje');
  137. end;
  138.  
  139. { TSegundaNuevaMostrar }
  140.  
  141. constructor TSegundaNuevaMostrar.Create;
  142. begin
  143.   Inherited Create;
  144.   FMostrarMensaje := TSegundaNuevaMostrarMensaje.Create;
  145.   FMostrarDialogo := TMostrarDialogo.Create;
  146.   FMostrarInput := TMostrarInput.Create
  147. end;



Espero que los ejemplos sean claros.

Gracias anticipadas!
  • 0




IP.Board spam blocked by CleanTalk.