Roles: Composable Units of Object Behavior

by chromatic

A significant new part of Perl 6's object model and type system is the addition of roles. Part of their origin is an implementation in Smalltalk (there called traits). They also solve some systemic problems of other OO systems.

Why are they useful and how do they work?


11 Comments

Frank Loebe
2006-08-31 08:43:53
An interesting discussion, to which I have rather questions than comments: is there any particular literature on which this entry is based? To what extent are roles implemented in Perl6 (I read that Perl6 is "on the way")? Is there any syntax specification for it (which I haven't found in few minutes; only the following page: http://dev.perl.org/perl6/doc/design/syn/S12.html containing sth on roles). Thanks.
Piers Cawley
2006-08-31 13:51:53
... inheritance isn't the fundamental principle of object orientation. Polymorphism is.


You know, I'd argue that 'polymorphism' (especially the sort practiced by static, pseudo OO languages) has become such a debased term that it's better to think of the real essence of object orientation as late binding - the target object decides, at runtime, how to deal with a message.


Which puts Multimethods in a slightly weird place, but they're slightly weird anyway, so that's okay.

chromatic
2006-08-31 15:18:43
Piers, I thought of explaining it in terms of genericity, but C++ has abused that so much (along with the notion of "compile time") that polymorphism seemed a better word.
Prose
2006-09-01 07:08:43
Hi chromatic
Are roles same as mixin's supported by Ruby? If not, what's the difference?
Ralphw
2006-09-01 14:16:56
So we have the term role, used to constrain the behaviour of objects.


Since Terry Halpin (recently at Microsoft, now returned to Academia) created Object Role Modeling, is this terminology consistent with that?



aufrank
2006-09-01 17:40:38
chromatic--


Thanks for writing this. It's definitely a useful description of the functionality of roles. After reading, I do have a couple of questions that I hope you can help me with.



First, you say:

What is a type? It's a role. It's a named collection of behavior.

Would you be willing to expand on the relationship between types and roles? Is the functionality of types a subset of the functionality of roles, or are the two really synonyms?


Second, Synopsis 12 gives an example of using an anonymous subtype in a signature:
sub check_even (Num $even where { $^n % 2 == 0 }) {...}
In your view, is this the same as declaring that $even does the Num role, declaring an anonymous role whose only parameter is constrained to be even, and then asserting that $even does that anonymous role? Is this an implementation issue or is dispatching types to roles central to the functionality you want roles to provide?


Thanks for any feedback,
/au

dami
2006-09-01 22:31:36
For an entry point to literature on roles, you may have a look at
www.iam.unibe.ch/~scg/Research/Traits/
chromatic
2006-09-02 02:23:26
Prose, Ruby mixins are similar to roles in that they add methods to classes (or instances, but then there's an anonymous parent class added) but different in that they do not participate in the type system. That is, to my knowledge, there's no built-in system in Ruby by which you can specify that a class or object must have mixed in a particular named bundle of methods. There's duck typing, but it has the false cognate problem.
chromatic
2006-09-02 02:29:49
aufrank, the connection between types and roles is that all types are roles. That is, to declare a type, you declare a role (or a class, or...). A role is a named collection of behavior about which you can reason certain things. That's the same thing as a type, at least if you buy into nominal typing.


That's my reasoning anyway.


As to your second question, I say that the signature declares an anonymous role that $even must perform. It's the job of the method dispatcher to check this. (In this case, it may be wise to check for Num-ness -- sorry -- before checking the subtype constraint.)


I may eventually regret suggesting that the words "role" and "type" are somewhat synonymous here.

Powerlord
2006-09-03 06:14:27
The problems come mostly from the poor design and implementation. Classes and interfaces occupy, apparently, separate namespaces in Java. The syntax for querying that an object or class extends another class is different from the syntax for querying that an object or class implements an interface.


What method were you using to check them? I tested the instanceof operator and it works on classes I've extended and interfaces I've implemented. More on this in a moment.


Recently, I was looking at Swing to build a simple GUI app in Java. One of the things recommended in Swing tutorials is the use of javax.swing.SwingUtilities.invokeLater() to asynchronously execute things on the GUI thread by adding them to a queue. invokeLater has a signature of public static void invokeLater(Runnable doRun)


Runnable is an interface, but you can't tell that by looking at invokeLater's method declaration.


To test instanceof's behavior, I wrote the following two objects. One of the objects implements Runnable and the other has a main thread to create an IRun object to test it using instanceof.


(The following text should contain tabs, but in the preview, something was still stripping them out, even inside preformatted text tags.)

// InstanceOfTest.java
public class InstanceOfTest
{
public static void main(String[] args)
{
IRun doRun = new IRun();
System.out.println(doRun instanceof Runnable);
}
}


// IRun.java
public class IRun implements Runnable
{
public void run()
{
System.out.println("I came, I saw, I ran!");
}
}



D:\Programming\Java\Instanceof Test>javac InstanceOfTest.java


D:\Programming\Java\Instanceof Test>java InstanceOfTest
true


D:\Programming\Java\Instanceof Test>


As you can see, doRun instanceof Runnable returns the boolean value true, which is implicitly converted to a string by System.out.prinln().
chromatic
2006-09-07 15:11:37
Powerlord, I just checked with Blackdown Java 1.3.1 (the latest version that I can convince to run on Linux/PPC unfortuantely), and you're right. My concern in the article was that you cannot use an interface name as a type in the signature of a method, but I just tested that and it worked correctly.


I still dislike the separation implied by implements and the abstractness of interfaces, but my other criticism was clearly wrong.