Título: NekroAyuda: Polimorfismo Publicado por: NekroByte en 11 Junio 2005, 02:23 am Polimorfismo Polimorfismo significa que muchas clases pueden proporcionar la misma propiedad o el mismo método y que el que llama no tiene por qué saber la clase a la que pertenece el objeto antes de llamar a la propiedad o al método. Por ejemplo, una clase Pulga y una clase Tiranosaurio podrían tener las dos un método Morder. El polimorfismo significa que puede invocar Morder sin saber si el objeto es una Pulga o un Tiranosaurio, aunque seguramente lo descubrirá después. Los siguientes temas describen la implementación del polimorfismo en Visual Basic y cómo puede usarlo en sus programas.
Título: Cómo proporciona Visual Basic el polimorfismo Publicado por: NekroByte en 11 Junio 2005, 02:28 am Cómo proporciona Visual Basic el polimorfismo La mayoría de los sistemas de programación orientada a objetos proporcionan polimorfismo mediante la herencia. Es decir, las hipotéticas clases Pulga y Tiranosaurio pueden heredar características de una clase Animal. Cada clase invalidaría el método Morder de la clase Animal para aportar sus propias características de mordedura. El polimorfismo proviene del hecho de que puede llamar al método Morder de un objeto que pertenezca a cualquier clase derivada de Animal sin conocer la clase a la que pertenece el objeto. Proporcionar polimorfismo mediante interfaces Visual Basic no utiliza la herencia para proporcionar polimorfismo. Visual Basic proporciona el polimorfismo mediante múltiples interfaces ActiveX. En el Modelo de objetos componentes (COM) que forma la infraestructura de la especificación ActiveX, las múltiples interfaces permiten que los sistemas de componentes software evolucionen sin afectar al código existente. Una interfaz es un conjunto de propiedades y métodos relacionados. Gran parte de la especificación ActiveX se ocupa de la implementación de interfaces estándar para obtener servicios del sistema o para proporcionar funcionalidad a otros programas. En Visual Basic podría crear una interfaz Animal e implementarla en las clases Pulga y Tiranosaurio. Después podría invocar el método Morder de cualquiera de los dos tipos de objeto sin conocer su tipo. Polimorfismo y rendimiento El polimorfismo es importante por razones de rendimiento. Para comprobarlo, observe la función siguiente: Código: Public Sub GetFood(ByVal Critter As Object, _ Los métodos Mover y Morder son enlaces en tiempo de compilación con Critter. El enlace en tiempo de compilación tiene lugar cuando Visual Basic no puede determinar en tiempo de compilación el tipo de objeto que contendrá una variable. En este ejemplo, el argumento Critter está declarado como As Object, de forma que en tiempo de ejecución pueda contener una referencia a cualquier tipo de objeto, como un Coche o una Roca. Como no puede saber cuál será el objeto, Visual Basic compila una parte de código adicional para preguntar al objeto si acepta el método llamado. Si el objeto acepta el método, dicho código adicional lo invoca; si no, el código adicional desencadena un error. Todas las llamadas a métodos o a propiedades incurren en esta carga adicional. Por el contrario, las interfaces permiten los enlaces en tiempo de diseño. Cuando Visual Basic conoce en tiempo de compilación la interfaz que se va a llamar, puede comprobar en la biblioteca de tipos si dicha interfaz acepta el método. Después, Visual Basic puede compilar un salto directo al método mediante una tabla virtual de funciones (vtable). Esto es muchas veces más rápido que el enlace en tiempo de compilación. Ahora suponga que los métodos Mover y Morder pertenecen a la interfaz Animal y que todas las clases de animales implementan esta interfaz. Ahora podría declarar el argumento Critter como As Animal y los métodos Mover y Morder se enlazarán en tiempo de diseño: Código: Public Sub GetFood(ByVal Critter As Animal, _ Título: Crear e implementar una interfaz Publicado por: NekroByte en 11 Junio 2005, 02:32 am Crear e implementar una interfaz Como se ha explicado en "Cómo proporciona Visual Basic el polimorfismo", una interfaz es un conjunto de propiedades y métodos. En el siguiente ejemplo de código se creará una interfaz Animal y se implementará en dos clases, Pulga y Tiranosaurio. Puede crear la interfaz Animal si agrega un módulo de clase al proyecto, le asigna el nombre Animal e inserta el código siguiente: Código: Public Sub Mover(ByVal Distance As Double) Observe que estos métodos no contienen código. Animal es una clase abstracta, que no contiene código de implementación. El propósito de una clase abstracta no es crear objetos, sino proporcionar una plantilla de interfaz que puede agregar a otras clases. No obstante, como verá, algunas veces resulta útil implementar la interfaz de una clase no abstracta; esto se describe más adelante en este tema. Nota Hablando con propiedad, una clase abstracta es una clase a partir de la cual no puede crear objetos. Siempre puede crear objetos a partir de clases de Visual Basic, incluso aunque no contengan código; así que no se pueden considerar realmente abstractas. Ahora puede agregar dos módulos de clase más. Asigne a uno de ellos el nombre Pulga y al otro Tiranosaurio. Para implementar la interfaz Animal en la clase Pulga, utilice la instrucción Implements: Código: Option Explicit En cuanto agregue esta línea de código, puede hacer clic en la lista desplegable (Objeto) de la izquierda de la ventana Código. Una de las entradas será Animal. Cuando la seleccione, la lista desplegable (Procedimiento) de la derecha mostrará los métodos de la interfaz Animal. Seleccione los métodos de uno en uno para crear plantillas de procedimiento vacías en todos los métodos. Las plantillas tendrán los argumentos y los tipos de datos correctos, como se han definido en la clase Animal. Cada nombre de procedimiento tendrá el prefijo Animal_ para identificar la interfaz. Importante Una interfaz es como un contrato. Al implementar la interfaz, una clase se compromete a responder cuando se invoque cualquier propiedad o método de la interfaz. Por tanto, debe implementar todas las propiedades y los métodos de una interfaz. Ahora puede agregar el código siguiente a la clase Pulga: Código: Private Sub Animal_Mover(ByVal Distance As Double) Puede que se pregunte por qué los procedimientos se declaran Private. Si fueran Public, los procedimientos Animal_Mover y Animal_Morder formarían parte de la interfaz Pulga y tendría el mismo enlace original, al declarar el argumento Critter As Object para que pueda contener una Pulga o un Tiranosaurio. Interfaces múltiples La clase Pulga tiene ahora dos interfaces: la interfaz Animal recién implementada, que tiene dos miembros, y la interfaz Pulga predeterminada, que no tiene miembros. Más adelante en este ejemplo se agregará un miembro a una de las interfaces predeterminadas. Puede implementar la interfaz Animal de forma similar para la clase Tiranosaurio: Código: Option Explicit Pruebas con el Tiranosaurio y la Pulga Agregue el código siguiente al evento Load de Form1: Código: Private Sub Form_Load() Presione F8 para recorrer el código. Observe los mensajes de la ventana Inmediato. Cuando la variable Código: anim se invoca la implementación de Morder de Pulga y de la misma forma para Tiranosaurio. La variable Código: anim objeto que implemente la interfaz Animal. De hecho, sólo puede contener referencias a dichos objetos. Si intenta asignar un objeto Form o PictureBox a Código: anim El método Morder se enlaza en tiempo de diseño cuando lo llama mediante Código: anim cualquier objeto asignado a Código: anim <H4>Paso de Tiranosaurios y Pulgas a procedimientos</H4> Recuerde el procedimiento GetFood (Alimentarse) de "¿Cómo proporciona Visual Basic el polimorfismo?". Puede agregar la segunda versión del procedimiento GetFood (el que ilustra el polimorfismo) a Form1 y sustituir el código del evento Load por el siguiente: Código: Private Sub Form_Load() El repaso de este código muestra cómo una referencia de objeto pasada a un argumento de otro tipo de interfaz se convierte en referencia a la segunda interfaz (en este caso, Animal). Lo que ocurre es que Visual Basic consulta el objeto para saber si acepta la segunda interfaz. Si el objeto lo acepta, devuelve una referencia a la interfaz y Visual Basic coloca esa referencia en la variable del argumento. Si el objeto no acepta la segunda interfaz, se produce un error. Implementar métodos que devuelven valores Suponga que el método Mover devolviera un valor. Después de todo, sabe cuánto quiere que se mueva el Animal, pero un espécimen concreto podría no ser capaz de llegar tan lejos. Podría estar viejo y decrépito o podría haber un muro en su camino. Puede usar el valor devuelto por el método Mover para saber indicarle el movimiento real del Animal. Código: Public Function Mover(ByVal Distance As Double) _ Cuando implemente este método en la clase Tiranosaurio, asigne el valor devuelto al nombre del procedimiento, como lo haría en cualquier otro procedimiento Function: Código: Private Function Animal_Mover(ByVal Distance _ Para asignar el valor devuelto, utilice el nombre completo del procedimiento, incluido el prefijo de la interfaz. Título: Breve descripción de objetos e interfaces Publicado por: NekroByte en 11 Junio 2005, 02:33 am Breve descripción de objetos e interfaces En este tema termina el ejemplo de código empezado en "Crear e implementar una interfaz" y continuado en "Implementar propiedades". Puede que le interese ver dichos temas antes de empezar éste. El ejemplo de código de Tiranosaurio y Pulga parece tratar con comodidad las interfaces y los objetos. Las referencias a objetos se asignan a una variable de objeto y las referencias a interfaces a otra. De hecho, todas las referencias son referencias de objeto. Una referencia a una interfaz también es una referencia al objeto que implementa la interfaz. Además, un objeto puede tener múltiples interfaces y seguir siendo el mismo objeto con todas ellas. En Visual Basic, cada clase tiene una interfaz predeterminada con el mismo nombre que la clase. Es casi lo mismo. Por convención se escribe un carácter de subrayado como prefijo del nombre de clase. El subrayado indica que esta interfaz se encuentra oculta en la biblioteca de tipos. De esta forma, la clase Tiranosaurio tiene una interfaz predeterminada llamada _Tiranosaurio. Como esta clase también implementa la interfaz Animal, tiene una segunda interfaz llamada Animal. Sin embargo, debajo de todas ellas el objeto sigue siendo un Tiranosaurio. Coloque un botón de comando en Form1 y agregue el código siguiente: Código: Private Sub Command1_Click() Puede que espere que el cuadro de mensajes presente "Animal", pero en realidad presenta "Tiranosaurio". Consultar las interfaces Cuando asigna un objeto Tiranosaurio a una variable de tipo Código: Animal interfaz Animal. El método utilizado recibe el nombre de QueryInterface o su abreviatura, QI; puede que algunas veces se encuentre QI utilizado como verbo. Si la respuesta es no, se produce un error. Si la respuesta es sí, el objeto se asigna a la variable. A través de dicha variable sólo se puede tener acceso a los métodos y propiedades de la interfaz Animal. Variables genéricas de objeto e interfaces ¿Qué ocurre si se asigna una referencia de objeto a una variable genérica de objeto, como en el código siguiente? Código: Private Sub Command1_Click() El resultado vuelve a ser un objeto Tiranosaurio. Y ahora, ¿qué interfaz obtiene cuando llama a las propiedades y los métodos mediante la variable Código: obj Tiranosaurio: Código: Public Sub Rugir() El método Rugir pertenece a la interfaz predeterminada del objeto Tiranosaurio. En el código del evento Click del botón de comando, sustituya la instrucción MsgBox por las dos líneas de código siguientes: Código: obj.Mover 42 Cuando ejecuta el proyecto y hace clic en el botón, la ejecución se detiene en el método Rugir, con el error "El objeto no acepta esta propiedad o método". Está claro que la interfaz sigue siendo Animal. Debe tener esto en cuenta cuando utilice variables de tipo Object con objetos que tienen múltiples interfaces. La interfaz a la que tiene acceso la variable es la última interfaz asignada. Por ejemplo: Código: Private Sub Command1_Click() Afortunadamente, no hay muchas razones a favor de usar los tipos de datos Object enlazados en tiempo de compilación, que son lentos, con los objetos que tienen múltiples interfaces. Una de las principales razones a favor del empleo de múltiples interfaces es la ventaja de disponer de enlaces en tiempo de diseño mediante el polimorfismo. Otros orígenes de interfaces Los módulos de clase de Visual Basic no son el único origen de interfaces implementables. Puede implementar cualquier interfaz contenida en una biblioteca de tipos si dicha interfaz acepta Automatización. Si tiene la Edición Profesional o la Edición Empresarial de Visual Basic, puede crear sus propias bibliotecas de tipos de clases abstractas. Dichas bibliotecas de tipos se pueden usar en muchos proyectos, como se describe en el tema "Principios generales del diseño de componentes" de Crear componentes ActiveX, en la Guía de herramientas componentes. La Edición Profesional y la Edición Empresarial también incluyen el programa MkTypLib (Generar biblioteca de tipos) en el directorio Tools. Si ha utilizado este programa en Microsoft Visual C++, puede que le parezca una manera más apropiada para crear interfaces. Usar interfaces en el proyecto Para usar una interfaz en el proyecto, haga clic en Referencias en el menú Proyecto para abrir el cuadro de diálogo Referencias. Si registró la biblioteca de tipos, aparecerá en la lista de referencias y podrá seleccionarla. Si la biblioteca de tipos no se encuentra en la lista, puede usar el botón Examinar para buscarla. En cuanto tenga una referencia a una biblioteca de tipos, puede usar Implements para implementar cualquiera de las interfaces de Automatización contenidas en la biblioteca de tipos. Título: Múltiples facetas (e interfaces) de la reutilización del código Publicado por: NekroByte en 11 Junio 2005, 02:37 am Múltiples facetas (e interfaces) de la reutilización del código Existen principalmente dos formas de reutilización del código: binario y origen. La reutilización de código binario se consigue mediante la creación y uso de un objeto, mientras que la reutilización de código fuente se consigue por herencia, lo que no se permite en Visual Basic. La reutilización de código fuente también se puede conseguir mediante la copia y modificación del código fuente, pero esta técnica no es nada nuevo y conlleva muchos problemas ya conocidos. Visual Basic ha sido uno de los pioneros en la reutilización de código binario; los controles son el ejemplo más clásico. Puede volver a usar el código de un control si coloca una instancia del control en un formulario. Esto se conoce como relación de contenedor o de posesión; por ejemplo, el formulario contiene o posee un control CommandButton. Para obtener más información Las relaciones de contenedores se describen en "Modelos de objetos", más adelante en este capítulo. Delegar en un objeto implementado Implements proporciona un medio eficaz para volver a usar el código. Puede implementar una clase abstracta, como se describe en "Crear e implementar una interfaz", o puede implementar la interfaz de una clase totalmente funcional. Puede crear el objeto interno (es decir, el objeto implementado) en el evento Initialize del objeto externo (el que implementa la interfaz del objeto interno). Como se menciona en "Crear e implementar una interfaz", una interfaz es como un contrato: tiene que implementar todos los miembros de la interfaz del objeto interno en el módulo de clase del objeto externo. Sin embargo, puede ser muy selectivo en la forma en que delega en las propiedades y los métodos del objeto interno. En un método podría delegar directamente en el objeto interno, mediante el paso de argumentos sin modificar, mientras que en otro método podría ejecutar parte del código antes de llamar al objeto interno y en un tercer método podría ejecutar únicamente su propio código y pasar por alto completamente el del objeto interno. Por ejemplo, suponga que tiene una clase HombreOrquesta y una clase Cacofonía que generan sonidos. Le gustaría agregar la funcionalidad de la clase Cacofonía a la clase HombreOrquesta y reusar parte de la implementación de los métodos de la clase Cacofonía. Código: ' HombreOrquesta implementa la interfaz Cacofonía. Ahora puede ir a la lista desplegable Objeto, seleccionar Cacofonía y después obtener las plantillas de procedimiento para los métodos de la interfaz Cacofonía. Para implementar dichos métodos, puede delegar en el objeto Cacofonía. Por ejemplo, el método Beep podría tener la apariencia siguiente: Código: Private Sub Cacofonía_Beep(ByVal Frequency As Double, _ La implementación anterior es muy sencilla. El objeto externo (HombreOrquesta) delega directamente en el interno (Cacofonía) y vuelve a usar el método Beep del objeto Cacofonía sin modificarlo. Esto está muy bien, pero es sólo el principio. La instrucción Implements es una herramienta de reutilización de código muy eficaz, puesto que ofrece gran flexibilidad. Puede que decida alterar el efecto del método Beep de la clase HombreOrquesta. Para ello, inserte su propio código antes, o después, de la llamada al objeto interno Cacofonía: Código: Private Sub Cacofonía_Beep(ByVal Frequency As Double, _ En algunos de los métodos, la implementación puede delegar directamente en el objeto interno Cacofonía, mientras que en otros puede interponer su propio código antes y después de delegar o incluso omitir la delegación si sólo utiliza su propio código para implementar un método. Como la clase HombreOrquesta implementa la interfaz Cacofonía, puede usarla con cualquier aplicación musical que llame a dicha interfaz. Los detalles de la implementación están ocultos para la aplicación que llama, pero los sonidos resultantes son los diseñados por usted. Nota COM proporciona otro mecanismo para la reutilización de código binario, llamado agregación. En la agregación se utiliza una interfaz completa sin modificaciones y la implementación la proporciona una instancia de la clase agregada. Visual Basic no acepta esta forma de reutilización de código. ¿No es tedioso? La escritura de código de delegación puede resultar muy tediosa, especialmente si la mayor parte de las propiedades y los métodos del objeto externo simplemente delegan de forma directa en las propiedades y los métodos correspondientes del objeto interno. Si tiene la Edición Profesional o la Edición Empresarial de Visual Basic, puede usar el Modelo de extensibilidad de Visual Basic para crear su propio asistente de delegación y automatizar la tarea, que es similar al Asistente de clases incluido en la Edición Profesional y en la Edición Empresarial. Para obtener más información El uso del polimorfismo y de las interfaces múltiples en los componentes software se describe en "Principios generales del diseño de componentes" de la sección Crear componentes ActiveX de la Guía de herramientas componentes. Título: Tema cerrado. Publicado por: NekroByte en 11 Junio 2005, 02:38 am Textos Extraidos de las Librerías de Microsoft Developer NetWork.
Dudas, comentarios, aclaraciones y consultas en otro hilo, en otro tema, en otra publicación, en otro post. Hilsener. |