Ir al contenido



Foto

Métodos extendidos (Agregando métodos a clases existentes)


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

#1 markdelphi

markdelphi

    Advanced Member

  • Moderadores
  • PipPipPip
  • 97 mensajes
  • LocationMéxico

Escrito 16 febrero 2009 - 05:40

En Delphi Prism podemos añadir un método a una clase existente, de este modo no tendremos que recompilar el objeto en particular, ni tendremos que crear un objeto nuevo derivado para poder añadir el nuevo método. Es posible añadir un nuevo método a un objeto existente con una nueva característica del compilador llamada “Métodos extendidos”. Podemos implementar una extensión de un método a cualquier tipo de la FCL (.NET Framework Class Library) o cualquier otro tipo .NET que queramos extender. A primera vista pareciera que este tipo de métodos es un atentado en contra de los principios de la programación orientada a objetos, esto no es tan grave siempre y cuando mantengamos un estricto control sobre su uso. Estos métodos son una base sobre la cual el framework sustenta características como LINQ y son muy útiles en ciertos casos, como cuando por ejemplo queremos agregar a una clase sellada (sealed) algún método para extender su funcionalidad.

Para definir un método extendido:

Agregamos el namespace “System.Runtime.CompilerServices” a la clausula Uses del nombre de espacio en donde estemos definiendo el método extendido. Este namespace contiene la definición de un atributo (el tema de los atributos se tratará más adelante)  llamado “ExtensionAttribute” que nos servirá para extender el método. Para hacer uso del atributo anteponemos [Extension] antes de la definición de la clase y antes de la definición del método a extender.


  • Agregamos el namespace “System.Runtime.CompilerServices” a la clausula Uses del nombre de espacio en donde estemos definiendo el método extendido. Este namespace contiene la definición de un atributo (el tema de los atributos se tratará más adelante)  llamado “ExtensionAttribute” que nos servirá para extender el método. Para hacer uso del atributo anteponemos [Extension] antes de la definición de la clase y antes de la definición del método a extender.
  • Definimos una clase estática que contenga el método a extender. Esta clase debe de ser visible para los clientes que la consuman.
  • Definir el método a extender, este debe de ser un método de clase y debe de estar definido en la sección public de la clase.
  • El primer parámetro del método especifica el tipo sobre el que él método opera.
  • En el  espacio de nombres en donde consumamos el método extendido agregamos a la clausula Uses el namespace que contiene la clase con el método de extendido.
  • Ahora ya podemos llamar al método normalmente, como si este método fuera parte de la clase desde un principio.

NOTA:

El primer parámetro no es especificado por el código de llamada porque representa el tipo sobre el que el operador está siendo aplicado, y el compilador ya sabe el tipo de objeto que debe de usar. Usted solamente tiene que suministrar valores a partir del segundo parámetro en adelante.

Veamos el siguiente ejemplo:

Vamos a definir un método extendido para la clase System.Int32 (es decir agregar un método al tipo Entero)  esté método devolverá el doble del valor que contenga la variable, el método se llamará “DoubleInSize”.
La clase que contiene el método extendido está definida en un nombre de espacio llamado “IntegerExtensions” que luce así:



delphi
  1. namespace IntegerExtensions;
  2.  
  3. interface
  4.  
  5. uses
  6.   System.Runtime.CompilerServices;
  7.  
  8. type
  9.   [Extension]
  10.   IntegerExtensions = public static class
  11.   public   
  12.     [Extension]
  13.     class method DoubleInSize (i : integer) : Integer;
  14.   end;
  15.  
  16. implementation
  17.  
  18.  
  19. class method IntegerExtensions.DoubleInSize ( i : integer) : Integer;
  20. begin
  21. Result:= i + i;
  22. end;
  23.  
  24. end.




Y el código que consume este método luce de la siguiente manera:



delphi
  1. uses
  2.   IntegerExtensions;
  3.  
  4.  
  5. Var i : Integer:=10;
  6. MessageBox.Show(i.DoubleInSize.ToString);






Hay que tener en mente ciertas cosas cuando vayamos a usar estos métodos:

1. El número de versión.- El número de versión de estos métodos es completamente independiente de la clase a la que afectan, esto puede provocar efectos no deseados cuando la clase sobre la cual se implementan sufre algún cambio.
2. El nombre del método.- El agregar un método a la clase sobre la cual se aplica el método podría hacer que el método de extensión asociado a la misma y con un nombre similar no se ejecutara, pues el miembro de la  instancia siempre tendrá preferencia sobre el método de extensión. El problema es que el compilador no podría avisar de algún problema, y en tiempo de ejecución es donde podrían aparecer las incompatibilidades entre ambos métodos.
3. Especificación de nombres de espacios incorrectos.- No hay forma de impedir que un mismo método de extensión sea definido en dos nombres de espacio diferentes, lo cual hace que el namespace indicado en la cláusula Uses sea el que esté decidiendo el método de extensión a ejecutar.   

La imagen muestra que intellisense muestra el método como si fuera parte de la propia clase.

  • 0

#2 Rolphy Reyes

Rolphy Reyes

    Advanced Member

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

Escrito 16 febrero 2009 - 06:56

Buen articulo compañero y bienvenido.

Solo para hacer una comparación con la "VCL", ¿estoy vendría a ser el Class Helpers?
  • 0

#3 markdelphi

markdelphi

    Advanced Member

  • Moderadores
  • PipPipPip
  • 97 mensajes
  • LocationMéxico

Escrito 16 febrero 2009 - 07:12

Así es Rolphy,  los Class Helpers  se introdujeron en Delphi 8 como una forma de hacer compatible a la VCL con .NET framework.
  • 0