Objetos y Meta-objetos

Objetos en Ozono

Un objeto en Ozono es en el fondo un objeto normal de Pharo. Es decir, es un objeto instancia de una clase. Como cada objeto en Ozono tiene un comportamiento distinto, cada uno de ellos va a tener una clase distinta. Las clases de los objetos de Ozono heredan de la clase OBObject. En OBObject se define el comportamiento base de los objetos de Ozono. Por ejemplo, el printString.

Todo objeto que manipulamos en un workspace de Ozono es una (sub)instancia de OBObject.

La clase OBObject no define ningún comportamiento que permite la manipulación del objeto, como ser agregar métodos o atributos. Para ello debe utilizarse el correspondiente meta-objeto que provee Ozono.

¿Qué es un meta-objeto?

En lenguajes basados en clases, las clases son aquellos objetos que describen a sus instancias. Por ejemplo, una clase en Pharo particularmente define entre otras cosas:
  • el comportamiento de un objeto a partir de aquellos métodos definidos en esa clase y relaciones con otras clases (superclases) y traits
  • el estado interno de un objeto a partir de una lista de atributos y sus nombres
Cuando un objeto se crea a partir de una clase, ese objeto tiene la forma que su clase define y entiende los mensajes para los cuales su clase (o superclase) definen comportamiento.

Mirándolo desde otro punto de vista, si a partir de un objeto, quisieramos tener una lista de sus variables de instancia, el objeto al que deberíamos preguntárselo es a su clase:

OrderedCollection instVarNames.     "Las variables de instancia definidas por esta clase"
OrderedCollection allInstVarNames.  "Las variables de instancia definidas por esta clase y sus superclases"

Lo mismo podríamos hacer con los métodos para entener qué mensajes entiende un objeto:

OrderedCollection methods.     "Los métodos definidos por esta clase"
OrderedCollection allMethods.  "Los métodos definidos por esta clase y sus superclases"

Estos objetos que describen a otros objetos, son aquellos que vamos a llamar meta-objetos (o meta objects). En contraste, a los objetos que son descriptos por meta-objetos vamos a llamarlos objetos-base (o base objects). Una relación particular que se da en la versión actual de Ozono es que cada objeto tiene una conexión causal con su meta-objeto. Es decir, cada vez que uno modifica a un meta-objeto ese cambio se ve reflejado en el objeto, y viceversa.

Meta-objetos en Ozono

Actualmente, Ozono permite manipular objetos individualmente. Cada objeto tiene sus atributos y métodos. Y cada objeto posee un prototipo a partir del cual basa también su estado y comportamiento. Este modelo difiere del modelo de clases con herencia simple de Pharo. Luego, lo que necesitamos es una forma distinta de meta objetos: los OBMetaObject.

Un OBMetaObject es un objeto que describe a un OBObject. Cuando manipulamos los métodos y atributos de un objeto en el browser de Ozono, estamos manipulando al OBMetaObject que describe a nuestro objeto. La relación entre un OBObject y OBMetaObject es uno a uno. En un workspace podemos validarlo de la siguiente manera:

pepita metaObject baseObject == pepita

Asimismo, podemos manipular los atributos de un objeto haciendo

pepita metaObject attributes.

pepita metaObject methods.


Creando Objetos y Meta-objetos en Ozono

Los objetos (y por ende sus meta-objetos) de ozono pertenecen a una lección. Para crear un objeto en una lección, se debe enviar el mensaje createObject a la misma.

lesson createObject

Ese método está implementado de la siguiente manera:

OBLesson >> createObject

    "Crea un meta-objeto y lo agrega en la lección"
| newObject |
newObject := OBMetaObject newOn: self.
self addObject: newObject.
^ newObject

OBMetaObject class>> newOn: aLesson

    "Crea un meta-objeto, luego un base-object, y los linkea"
| concreteClass concreteObject metaObject |
metaObject := self new.
concreteClass := self createNewObjectBrowserObjectClassIn: aLesson.
concreteObject := concreteClass new.
concreteObject metaObject: metaObject.
^ metaObject
concreteObject: concreteObject;
lesson: aLesson;
yourself.

Behind the Scenes: Objetos Meta/Base y Clases en Pharo

Para no tener que implementar un propio intérprete y poder utilizar la infraestructura ya existente en Pharo, tanto objetos como meta-objetos están implementados como objetos Pharo. Cada objeto del object browser tiene, además de su meta objeto instancia de OBMetaObject, una clase de Pharo asociada (subclase de OBObject). Por ejemplo, si creásemos un objeto pepita, tendríamos en el sistema las clases tal como se muestran en el siguiente diagrama:

pepita es un objeto instancia de OBPepita. OBPepita es una clase anónima (y escondida) creada por Ozono, subclase de OBObject. La relación entre OBObject y OBMetaObject es bidireccional.

Cada vez que instanciamos un OBMetaObject en ozono, este crea a su vez una clase anónima y una instancia de esta, tal como muestra la figura de arriba. pepita es un objeto instancia de OBPepita. OBPepita es una clase anónima subclase de OBObject. Por clase anónima queremos decir que es una clase que no se va a registrar en el sistema: no va a aparecer en browsers ni commitearse en monticello.

La creación de clases anónimas se lleva a cabo en el método

OBMetaObject class >> createNewObjectBrowserObjectClassIn: aLesson
^ aLesson
createClass: (OBObject name, self takeSequencialNumber asString) asSymbol
subclassOf: OBObject

Como puede verse en el código de arriba, el nombre de la clase anónima en realidad esta compuesta por el nombre de la clase OBObject y un número secuencial, para evitar conflictos de nombres (Guille dice: Habría que revisar esta decisión. Una clase tiene que estar registrada en un environment (tiene?). Por ende, cada lección tiene un environment donde las clases son creadas y registradas: es por esto que se evita la colisión de nombres).

Noten que en Ozono uno nunca debería manipular directamente la clase de un objeto: es el OBMetaObject el único que esta autorizado a hacerlo.
Comments