This document attempts to explain the Meta-Meta-Class hierarchy and implementation.
.............> MetaClass <............... : | : ---> isSubclassOf : | : ...> isInstanceOf : V : - -> does() : Class::Behavior<----------+ : : | | : : | | : : V | : : +------> Role::Behavior | : : | | | : metaclass(Role) | ..... > metaclass(Class) ^ V : : Object : : | : : | : : V : Role < - - - - - Class ... role Role {} class Class does Role {} class Object is Class {} class Role::Behavior is Object {} class Class::Behavior is Role::Behavior {} class MetaClass is Class::Behavior {} my $Role = MetaClass.new('Role'); $Role.superclass(Role::Behavior); my $Class = MetaClass.new('Class'); $Class.superclass(Class::Behavior); $Class.roles($Role);
Or a sligthly different view of the same:
+--{ Implementation Layer }--------------------+ | | ---> isSubclassOf | +----------->Role::Behavior | ...> isInstanceOf | | ^ | - -> does() | | | | | | Class::Behavior<-----------+ | | | ^ | | +---|------------------|-------------------|---+ | | | | | | | | | | | Role .........> MetaClass <.......... Class | | ^ | | | + - - - - - - - - - - - - - - - - - - -+ | | | +---------------{ Meta Space }-----------------+
A Role is flattened into either a Class or another Role. This act of flattening negates any real "hierarchy" like that of a Class hierarchy.
This is an important distinction to remember.
Duck typing is usually described like this:
If it quacks like a duck, it must be a duck.
Which basically means that a Type is defined by the methods it responds to, instead of some label it has been given. However, this is a very simple defintion of duck-typing from the users point of view, and fails to explain it from the implementation point of view.
From the implementation point-of-view, duck-typing means that instead of an object's behavior being defined by a class, it is defined by a Type entity which exists in the somewhat muddy area between Class and Instances.
[ Class + [ Role, ... ]] --> ::Type <--- Instances
A class and it's attached roles are "compiled" into a Type, which is then used by instances in the system.
The behavior of classes and roles must be described somehow, and we should be able to re-use that implementation as well.
I propose a Class::Behavior and Role::Behavior implementation.
A Role::Behavior has a hash of methods and a hash of properties, as well as an array of Roles. Role::Behavior encapsulates all of the behavior needed to compose a Role.
A Class::Behavior is a subclass of Role::Behavior because a class also has a hash of methods and properties and an array of roles. It then adds to that with a parent class as well as a set of subclasses. Class::Behavior encapsulates all of the behavior needed to compose a Class.
The Meta Space contains all of our meta-objects of which I see 3 distinct types.
This is the "root" of our MetaClass hierarchy, and the loopback point of our object model. It is a subclass of Class::Behavior.
The Role is itself an instance of the MetaClass, but it is also a subclass of the Role::Behavior.
The Class too is an instance of the MetaClass, and it is a subclass of Class::Behavior.
The Class also does() the role Role.
NOTE: this Class.does(Role) relationship may not be needed, but I am leaving it in for now.
metametaclass MetaClass is Class::Behavior { has $.name; has @:roles; has $:superclass; has @:subclasses; has %.properties; has %.methods; method addProperties {} method addMethods {} method invokeMethod {} method super { ... } # a class must be able to inherit from another class method subclasses { ... } # a class must be able to be inherited from method doesRole {} # doing a Role just folds properties and methods into the metaclass } my $Role = MetaClass.new('Role'); # metaclass(Role) is an instance of metametaclass(MetaClass) $Role.superclass(Role::Behavior); $Role.addProperties( $.name, @:roles, %:properties, %:methods ); $Role.addMethods( roles ); # Hmmm,... MetaClass and Role look suspiciously similar my $Class = MetaClass.new('Class'); # metaclass(Class) is an instance of metametaclass(MetaClass) $Class.superclass(Class::Behavior); $Class.doesRole($Role); $Class.addProperties( $:superclass, @:subclasses ); $Class.addMethods( super, subclasses, invokeMethod );
When "compiled" the metaclass(Role) will look something like this:
metaclass Role is Role::Behavior { has $.name; has @.roles; has %.properties; has %.methods; method roles { ... } # a role must be able to attach other roles to it # property access is made possible through methods }
NOTE: In order for the metaclass(Role) to be able to compose more roles, it must have all the methods of a Role::Behavior. Since we don't want these methods to actually be inherited down to the next level (the "user" space), we make the metaclass inherit from Role::Behavior in the implementation itself, and not as a superclass(). The same is done for metaclass(Class) and Class::Behavior.
superclass()
my $bar_role = Role.new('Bar'); # role(Bar) is an instance of metaclass(Role) $bar_role.addProperties( $.baz ); $bar_role.addMethods( baz );
Can then be "compiled" into this role(Bar):
role Bar { has $.baz; method baz { ... } }
When "compiled" the metaclass(Class) will look like this:
metaclass Class is Class::Behavior does metaclass(Role) { # the following properties are from metaclass(Role) # $.name, @.roles, %.properties, %.methods; # the following methods too # roles(), invokeMethod() has @.superclasses; has @.subclasses; method super { ... } # a class must be able to inherit from another class method subclasses { ... } # a class must be able to be inherited from method invokeMethod { ... } } my $foo_class = Class.new('Foo'); # class(Foo) is an instance of metaclass(Class) $foo_class.doesRole('Bar'); $foo_class.addProperties( $.foo ); $foo_class.addMethods( foo );
This can then be compiled into this class(Foo):
class Foo { has $.foo; has $.baz; method foo { ... } method baz { ... } }
Stevan Little <stevan@iinteractive.com>
To install Perl6::Pugs, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Perl6::Pugs
CPAN shell
perl -MCPAN -e shell install Perl6::Pugs
For more information on module installation, please visit the detailed CPAN module installation guide.