stringtranslate.com

Metaclase

En la 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 los comportamientos de los objetos, las metaclases especifican los comportamientos 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 tienen las metaclases sobre los comportamientos de las clases varía. Las metaclases a menudo se implementan tratando a las clases como ciudadanos de primera clase , lo que convierte a una metaclase en 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 simple clase de Python:

clase  Auto :  def  __init __ ( self ,  marca :  str ,  modelo :  str ,  año :  int ,  color :  str )  : self.marca = make self.modelo = modelo self.año = año self.color = color            @property  def  description ( self )  ->  str : """Devuelve una descripción de este coche.""" return f " { self . color } { self . make } { self . model } "     

En tiempo de ejecución, Cares una instancia de type. El código fuente de la Carclase, que se muestra arriba, no incluye detalles como el tamaño en bytes de Carlos objetos, su distribución binaria en memoria, cómo se asignan, que el __init__método se llama automáticamente cada vez Carque se crea a, etc. Estos detalles entran en juego no solo 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 de . 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, crea el objeto de la forma predeterminada normal.  obj  =  type . __call__ ( self ,  * args ) # Además, establezca atributos en el nuevo objeto.  para  nombre ,  valor  en  kwargs . items ():  setattr ( obj ,  nombre ,  valor ) # Devuelve el nuevo objeto.  return  obj

Esta metaclase solo anula la creación de objetos. Todos los demás aspectos del comportamiento de la clase y del objeto siguen siendo manejados por type.

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

clase  Car ( object ,  metaclass = AttributeInitType ):  @property  def  description ( self )  ->  str : """Devuelve una descripción de este coche.""" return " " .join ( str ( value ) for value in self .__ dict __ . values ())       

El objeto resultante Carse puede instanciar como 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 las relaciones de herencia e 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).

Como ejemplo, un objeto de automóvil ces una instancia de la clase Car. A su vez, la clase Cares nuevamente un objeto y, como tal, una instancia de la metaclase de Carllamada Car class. Observe 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 para Carcuyo nombre es Car class(se puede confirmar esto evaluando Car class nameque devuelve el nombre de la metaclase de Car).

Los métodos de clase pertenecen en realidad 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 la superclase y se detiene en Object, independientemente de si se encuentra o no.

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

En los primeros 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 tuvieran sus propios métodos y sus propias variables de instancia (llamadas variables de instancia de clase y que no deben confundirse con las 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 única clase llamada Metaclass. MetaclassSe llama a la metaclase de Metaclass classque, a su vez, es una instancia de la 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 la clase Object. TODAS las metaclases son subclases de Class, por lo tanto:

Al igual que los gemelos unidos , las clases y las metaclases nacen juntas. Metaclasstiene una variable de instancia thisClassque apunta a su clase unida. Tenga en cuenta que el explorador de clases habitual de Smalltalk no muestra las metaclases como clases separadas. En cambio, el explorador 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 funciones necesarias para describir nuevas clases. Su jerarquía de herencia (de Object) y las principales funciones que proporcionan 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 ): nombres de clases y variables, comentarios
Clase: instalaciones similares y más completas que 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 introduciendo clases propias, eliminando la Metaclassclase y redefiniendo (o des)el mapa de clases. El cambio se puede esquematizar de la siguiente manera: [6]

Obsérvese en particular la correspondencia entre las metaclases implícitas de Smalltalk y las clases propias de Ruby. El modelo de clases propias de Ruby hace que el concepto de metaclases implícitas sea completamente uniforme: cada objeto x tiene su propio metaobjeto, llamado la clase propia de x , que es un metanivel superior a x . Las clases propias de "orden superior" suelen existir de forma puramente conceptual: 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 muestra de la estructura central de Smalltalk-80 y Ruby en comparación. [8] En ambos lenguajes, 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 By objetos 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 de instanciación de miembro complementario→contenedor (un enlace azul desde x apunta al contenedor menos real de x que es el punto de inicio para la búsqueda de método cuando se invoca un método en x ). Los nodos grises muestran las clases propias (resp. metaclases implícitas en el caso de Smalltalk-80).

El diagrama de la derecha también ofrece una imagen de la evaluación diferida de clases propias en Ruby. El vobjeto puede tener su clase propia evaluada (asignada) como consecuencia de agregar métodos singleton a v.

Según el método de introspección de Ruby llamado class, la clase de cada clase (y de cada eigenclass) es constantemente la Classclase (denotada por cen el diagrama). Class, y 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, difiere en la restricción a clases. Como ya se mencionó anteriormente, para una clase x, la expresión de Ruby x.classevalúa constantemente a Class. En Smalltalk-80, si xes una clase entonces la expresión x classcorresponde a la de Ruby x.singleton_class– que evalúa a la eigenclass de x.

En Objective-C

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

Las metaclases en Objective-C son casi las mismas que en Smalltalk-80, lo cual no sorprende ya que Objective-C toma mucho de Smalltalk. Al igual que Smalltalk, en Objective-C las variables de instancia y los métodos están definidos por la clase de un objeto. Una clase es un objeto, por lo 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 las diferentes clases pueden tener diferentes conjuntos de métodos de clase, cada clase debe tener su propia metaclase independiente. Las clases y las metaclases siempre se crean como un par: el entorno de ejecución tiene funciones objc_allocateClassPair()y objc_registerClassPair()para crear y registrar pares de 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 el de la clase raíz.

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

Dado que los objetos de metaclase no se comportan de forma 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 lo 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 lo 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 difundidos que admiten metaclases son OpenJava , OpenC++, OpenAda, CorbaScript , ObjVLisp, Object-Z , MODEL-K, XOTcl y MELDC. Varios de estos lenguajes datan de principios de los años 1990 y son de interés académico. [12]

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

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

Véase también

Referencias

  1. ^ Ira R. Forman y Scott Danforth (1999). Poner las metaclases en práctica . Addison-Wesley. ISBN 0-201-43305-2.
  2. ^ AloorRavi, Sulekha (2022). Metaprogramación con Python . Birmingham: Packt Publishing.
  3. ^ Programación de metaclases de IBM 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. "A Primer on Python Metaclass Programming" (Una introducción a la programación de metaclases en Python). ONLamp . 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 Ruby. Pragmatic Bookshelf. ISBN 978-1-934356-47-0.
  8. ^ "Pertenencia a objetos: la estructura central de la tecnología de objetos".
  9. ^ "Estructura". Ruby Doc . Consultado el 1 de mayo de 2015 .
  10. ^ Cacao con amor: ¿Qué es una metaclase en Objective-C?
  11. ^ Herb Sutter . "Metaclases" (PDF) .
  12. ^ "Una implementación de mixins en Java usando metaclases" (PDF) . Archivado desde el original (PDF) el 2007-10-16 . Consultado el 2007-11-27 .

Enlaces externos