stringtranslate.com

Metaclase

En programación orientada a objetos , una metaclase es una clase cuyas instancias son clases en sí mismas. A diferencia de las clases ordinarias, que definen el comportamiento de los objetos, las metaclases especifican el comportamiento de las clases y sus instancias. No todos los lenguajes de programación orientados a objetos admiten el concepto de metaclases. Para aquellos que lo hacen, el grado de control que las metaclases tienen sobre los comportamientos de clase varía. Las metaclases a menudo se implementan tratando a las clases como ciudadanos de primera clase , haciendo de una metaclase un objeto que crea y administra estas clases. Cada lenguaje de programación se adhiere a su propio protocolo de metaobjetos , que son las reglas que determinan las interacciones entre objetos, clases y metaclases. [1] Las metaclases se utilizan para automatizar la generación de código y mejorar el desarrollo del marco. [2]

Ejemplo de Python

En Python , la clase incorporada typees una metaclase. [3] [4] [5] Considere esta sencilla clase de Python:

clase  Coche :  def  __init__ ( self ,  marca :  str ,  modelo :  str ,  año :  int ,  color :  str ):  self . hacer  =  hacerse  uno mismo . modelo  =  modelo  de sí mismo . año  =  año  yo . color  =  color @property  def  descripción ( self )  ->  str : """Devolver una descripción de este automóvil.""" return f " { self . color } { self . make } { self . model } "     

En tiempo de ejecución, Carél mismo es una instancia de type. El código fuente de la Carclase, mostrado arriba, no incluye detalles como el tamaño en bytes de los Carobjetos, su disposición binaria en la memoria, cómo se asignan, que el __init__método se llama automáticamente cada vez que Carse crea a, etc. Estos detalles entran en juego no sólo cuando Carse crea un nuevo objeto, sino también cada vez que Carse accede a cualquier atributo de a. En lenguajes sin metaclases, estos detalles están definidos por la especificación del lenguaje y no se pueden anular. En Python, la metaclase typecontrola estos detalles del Carcomportamiento. Se pueden anular utilizando una metaclase diferente en lugar de type.

El ejemplo anterior contiene código redundante relacionado con los cuatro atributos make, model, yeary color. Es posible eliminar parte de esta redundancia utilizando una metaclase personalizada. En Python, una metaclase se define más fácilmente como una subclase de type.

clase  AttributeInitType ( tipo ):  def  __call__ ( self ,  * args ,  ** kwargs ): "" "Crear una nueva instancia."""  # Primero, cree el objeto de la forma predeterminada normal.  obj  =  tipo . __llamar__ ( yo ,  * argumentos ) # Además, establezca atributos en el nuevo objeto.  para  nombre ,  valor  en  kwargs . elementos ():  setattr ( obj ,  nombre ,  valor ) # Devolver el nuevo objeto.  objeto de retorno 

Esta metaclase solo anula la creación de objetos. Todos los demás aspectos del comportamiento de clases y objetos todavía son manejados por type.

Ahora la clase Carse puede reescribir para usar esta metaclase. En Python 3 esto se hace proporcionando un "argumento de palabra clave" metaclassa la definición de clase:

clase  Coche ( objeto ,  metaclase = AttributeInitType ):  @property  def  descripción ( self )  ->  str : """Devuelve una descripción de este coche.""" return " " . unirse ( str ( valor ) para valor en self . __dict__ . valores ())       

Se puede crear una instancia del objeto resultante Carcomo de costumbre, pero puede contener cualquier número de argumentos de palabras clave:

new_car  =  Coche ( marca = 'Toyota' ,  modelo = 'Prius' ,  año = 2005 ,  color = 'Verde' ,  motor = 'Híbrido' )

En Smalltalk-80

La jerarquía de metaclases de Smalltalk-80 como diagrama UML
Diagrama de herencia y relaciones de instancia entre clases y metaclases en Smalltalk

En Smalltalk , todo es un objeto . Además, Smalltalk es un sistema basado en clases , lo que significa que cada objeto tiene una clase que define la estructura de ese objeto (es decir, las variables de instancia que tiene el objeto) y los mensajes que entiende un objeto. En conjunto, esto implica que una clase en Smalltalk es un objeto y que, por lo tanto, una clase debe ser una instancia de una clase (llamada metaclase).

Por ejemplo, un objeto automóvil ces una instancia de la clase Car. A su vez, la clase Carvuelve a ser un objeto y, como tal, una instancia de la metaclase de Carcall Car class. Tenga en cuenta el espacio en blanco en el nombre de la metaclase. El nombre de la metaclase es la expresión de Smalltalk que, cuando se evalúa, da como resultado el objeto de metaclase. Por lo tanto, la evaluación Car classda como resultado el objeto de metaclase Carcuyo nombre es Car class(se puede confirmar esto evaluando Car class namecuál devuelve el nombre de la metaclase de Car).

Los métodos de clase en realidad pertenecen a la metaclase, al igual que los métodos de instancia pertenecen en realidad a la clase. Cuando se envía un mensaje al objeto 2, la búsqueda del método comienza en Integer. Si no se encuentra, continúa hacia arriba en la cadena de superclases, deteniéndose en el Objeto, ya sea que se encuentre o no.

Cuando se envía un mensaje a Integerla búsqueda, el método comienza en Integer classy continúa por la cadena de superclase hasta Object class. Tenga en cuenta que, hasta ahora, la cadena de herencia de metaclases sigue exactamente a la cadena de herencia de clases. Pero la cadena de metaclases se extiende más allá porque Object classes la subclase de Class. Todas las metaclases son subclases de Class.

Al principio de Smalltalks, solo había una metaclase llamada Class. Esto implicaba que los métodos que tenían todas las clases eran los mismos, en particular el método para crear nuevos objetos, es decir, new. Para permitir que las clases tengan sus propios métodos y sus propias variables de instancia (llamadas variables de instancia de clase y no deben confundirse con variables de clase ), Smalltalk-80 introdujo para cada clase Csu propia metaclase C class. Esto significa que cada metaclase es efectivamente una clase singleton .

Dado que no existe ningún requisito de que las metaclases se comporten de manera diferente entre sí, todas las metaclases son instancias de una sola clase llamada Metaclass. MetaclassSe llama a la metaclase de, Metaclass classque nuevamente es una instancia de clase Metaclass.

En Smalltalk-80, cada clase (excepto Object) tiene una superclase . La superclase abstracta de todas las metaclases es Class, que describe la naturaleza general de las clases.

La jerarquía de superclases para las metaclases es paralela a la de las clases, excepto para class Object. TODAS las metaclases son subclases de Class, por lo tanto:

Al igual que los gemelos siameses , las clases y metaclases nacen juntas. Metaclasstiene una variable de instancia thisClass, que apunta a su clase conjunta. Tenga en cuenta que el navegador de clases Smalltalk habitual no muestra las metaclases como clases separadas. En cambio, el navegador de clases permite editar la clase junto con su metaclase al mismo tiempo.

Los nombres de las clases en la jerarquía de metaclases se confunden fácilmente con los conceptos del mismo nombre. Por ejemplo:

Cuatro clases proporcionan las facilidades para describir nuevas clases. Su jerarquía de herencia (de Objeto) y las principales facilidades que brindan son:

Objeto: comportamiento predeterminado común a todos los objetos, como el acceso a clases.
Comportamiento: estado mínimo para compilar métodos y crear/ejecutar objetos
ClassDescription ( clase abstracta ): denominación de clase/variable, comentarios
Clase: instalaciones similares y más completas a las superclases
Metaclase: inicialización de variables de clase, mensajes de creación de instancias

en rubí

Ruby purifica el concepto de metaclases de Smalltalk-80 al introducir clases propias, eliminar la Metaclassclase y (des)redefinir el mapa de clases. El cambio se puede esquematizar de la siguiente manera: [6]

Tenga en cuenta en particular la correspondencia entre las metaclases implícitas de Smalltalk y las clases propias de clases de Ruby. El modelo de clase propia de Ruby hace que el concepto de metaclases implícitas sea completamente uniforme: cada objeto x tiene su propio metaobjeto, llamado clase propia de x , que es un metanivel superior a x . Las clases propias de "orden superior" generalmente existen puramente conceptualmente: no contienen ningún método ni almacenan ningún (otro) dato en la mayoría de los programas Ruby. [7]

Los siguientes diagramas muestran una estructura central de muestra de Smalltalk-80 y Ruby en comparación. [8] En ambos idiomas, la estructura consta de una parte incorporada que contiene los objetos circulares (es decir, objetos que aparecen en un ciclo formado por una combinación de enlaces azules o verdes) y una parte de usuario que tiene cuatro objetos explícitos: clases Ay Bobjetos terminales uy v. Los enlaces verdes muestran la relación de herencia hijo→padre (con la dirección ascendente implícita), los enlaces azules muestran la relación complementaria de creación de instancias miembro→contenedor (un enlace azul desde x apunta al contenedor menos real de x que es el punto de partida para la búsqueda de métodos cuando se invoca un método en x ). Los nodos grises muestran las clases propias (respectivamente, metaclases implícitas en el caso de Smalltalk-80).

El diagrama de la derecha también proporciona una imagen de la evaluación diferida de clases propias en Ruby. Al vobjeto se le puede evaluar (asignar) su clase propia como consecuencia de agregar métodos singleton a v.

Según el método de introspección de Ruby denominado class, la clase de cada clase (y de cada clase propia) es constantemente la Classclase (indicada por cen el diagrama). Classy Structson las únicas clases que tienen clases como instancias. [9] [ disputadodiscutir ] La subclasificación de Classno está permitida. Siguiendo la definición estándar de metaclases podemos concluir que Classy Structson las únicas metaclases en Ruby. Esto parece contradecir la correspondencia entre Ruby y Smalltalk, ya que en Smalltalk-80 cada clase tiene su propia metaclase. La discrepancia se basa en el desacuerdo entre el classmétodo de introspección en Ruby y Smalltalk. Mientras que el mapa x ↦ x.class coincide en objetos terminales, se diferencia en la restricción a clases. Como ya se mencionó anteriormente, para una clase x, la expresión Ruby x.classse evalúa constantemente como Class. En Smalltalk-80, si xes una clase, entonces la expresión x classcorresponde a Ruby x.singleton_class, que se evalúa como la clase propia de x.

En Objective-C

Diagrama de las relaciones de herencia y instancia entre clases y metaclases en Objective-C. Tenga en cuenta que Objective-C tiene múltiples clases raíz; cada clase raíz tendría una jerarquía separada. Este diagrama solo muestra la jerarquía de un ejemplo de clase raíz NSObject. Cada otra clase raíz tendría una jerarquía similar.

Las metaclases en Objective-C son casi las mismas que las de Smalltalk-80, lo que no es sorprendente ya que Objective-C toma prestado mucho de Smalltalk. Al igual que Smalltalk, en Objective-C, las variables y métodos de instancia están definidos por la clase de un objeto. Una clase es un objeto, por tanto es una instancia de una metaclase.

Al igual que Smalltalk, en Objective-C, los métodos de clase son simplemente métodos llamados en el objeto de clase, por lo tanto, los métodos de clase de una clase deben definirse como métodos de instancia en su metaclase. Debido a que diferentes clases pueden tener diferentes conjuntos de métodos de clase, cada clase debe tener su propia metaclase separada. Las clases y metaclases siempre se crean como un par: el tiempo de ejecución tiene funciones objc_allocateClassPair()y objc_registerClassPair()para crear y registrar pares clase-metaclase, respectivamente.

No hay nombres para las metaclases; sin embargo, se puede hacer referencia a un puntero a cualquier objeto de clase con el tipo genérico Class(similar al tipo idque se utiliza para un puntero a cualquier objeto).

Debido a que los métodos de clase se heredan a través de herencia, como Smalltalk, las metaclases deben seguir un esquema de herencia paralelo al de las clases (por ejemplo, si la clase padre de la clase A es la clase B, entonces la clase padre de la metaclase de A es la metaclase de B), excepto la de la clase raíz.

A diferencia de Smalltalk, la metaclase de la clase raíz hereda de la propia clase raíz (generalmente NSObjectusando el marco Cocoa ). Esto garantiza que todos los objetos de clase sean, en última instancia, instancias de la clase raíz, de modo que pueda utilizar los métodos de instancia de la clase raíz, normalmente métodos de utilidad útiles para objetos, en los propios objetos de clase.

Dado que los objetos de metaclase no se comportan de manera diferente (no se pueden agregar métodos de clase para una metaclase, por lo que todos los objetos de metaclase tienen los mismos métodos), todos son instancias de la misma clase: la metaclase de la clase raíz (a diferencia de Smalltalk). Por tanto, la metaclase de la clase raíz es una instancia de sí misma. La razón de esto es que todas las metaclases heredan de la clase raíz; por tanto, deben heredar los métodos de clase de la clase raíz. [10]

Soporte en idiomas y herramientas

Los siguientes son algunos de los lenguajes de programación más destacados que admiten metaclases.

Algunos lenguajes menos extendidos que admiten metaclases incluyen OpenJava , OpenC++, OpenAda, CorbaScript , ObjVLisp, Object-Z , MODEL-K, XOTcl y MELDC. Varios de estos idiomas datan de principios de la década de 1990 y son de interés académico. [12]

Logtalk , una extensión de Prolog orientada a objetos , también admite metaclases.

El Marco de descripción de recursos (RDF) y el Lenguaje de modelado unificado (UML) admiten metaclases.

Ver también

Referencias

  1. ^ Ira R. Forman y Scott Danforth (1999). Poniendo las metaclases a trabajar . Addison-Wesley. ISBN 0-201-43305-2.
  2. ^ AloorRavi, Sulekha (2022). Metaprogramación con Python . Birmingham: Packt Publishing.
  3. ^ Programación IBM Metaclass en Python, partes 1 Archivado el 3 de septiembre de 2008 en Wayback Machine , 2 y 3
  4. ^ Foro Artima: Metaclases en Python 3.0 (parte 1 de 2) (parte 2 de 2)
  5. ^ David Mertz. "Introducción a la programación de metaclases de Python". Lámpara ON . Archivado desde el original el 30 de abril de 2003 . Consultado el 28 de junio de 2006 .
  6. ^ "El modelo de objetos Ruby: comparación con Smalltalk-80".
  7. ^ Paolo Perrotta (2010). Metaprogramación de Ruby. Estantería pragmática. ISBN 978-1-934356-47-0.
  8. ^ "Membresía de objetos: la estructura central de la tecnología de objetos".
  9. ^ "Estructura". Doctor Rubí . Consultado el 1 de mayo de 2015 .
  10. ^ Cocoa with Love: ¿Qué es una metaclase en Objective-C?
  11. ^ Hierba Sutter . "Metaclases" (PDF) .
  12. ^ "Una implementación de mixins en Java utilizando metaclases" (PDF) . Archivado desde el original (PDF) el 16 de octubre de 2007 . Consultado el 27 de noviembre de 2007 .