Index

This file was automatically generated from http://svn.pugscode.org/pugs/docs/tutorial/ch06_objects.pod on Sat Aug 1 14:01:20 2009 GMT, revision 27701.


=head0 Objects

Objects are encapsulated chunks of data and functionality. Over the years a host of concepts have sprung up around objects, such as data abstraction, code reuse, encapsulation, single and multiple inheritance, composition, delegation, mixins, polymorphism, and multiple dispatch. Every language with object-oriented syntax selects a subset of these ideas and combines them in different ways. With Perl 6 we want to provide a cleaner and simpler syntax for working with objects, but we also want to support a larger set of object-oriented ideas. Does that sound impossible? The solution is a classically Perl-ish one: make the easy things easy and the hard things possible.

Using Objects

You can declare a class in one of two ways. The most familiar syntax for class declaration ends in a semicolon. The rest of the file after the declaration defines the class. With this syntax there can be only one class or module declaration in a file.

  class Heart::Gold;
  # class definition follows
  ...

The class declaration extends to the very end of the file, although in Perl 6 the file doesn't need to return a 1 or a true to indicate that the module loaded successfully.

The other syntax for class declaration wraps the definition in a block. You can have as many of these as you like in a file, and even embed one class within the block of another.

  class Heart::Gold {
      # class definition enclosed
      ...
  }

And an embedded class:

  class Heart::Gold {
      # class definition here

      class Heart::Gold::InfiniteImprobabilityDrive {
          # sub-class definition here
      }
      
      class Heart::Gold::Ship {
          # Another sub-class definition here
      }
  }

With a file definition, all code that follows the class declaration is defined in the Heart::Gold namespace. With a block definition, everything within the block is defined in the class's namespace.

To create a new object from a class, simply call its new method. The default new method in the universal base class Object creates and initializes an object.

  Heart::Gold $ship;
  $ship = Heart::Gold.new(length => 150);

There's a shortcut for typed variables so you don't have to give the name of the class twice:

  my Heart::Gold $ship .= new(length => 150);

The .= operator is like other assignment operators such as += and -=. The two declarations are equivalent:

  my Heart::Gold $ship;
  $ship = Heart::Gold.any_method()
  
  my Heart::Gold $ship .= any_method()

The . symbol is almost always associated with classes, their methods, and their members, so anyplace you see it you can assume it has something to do with a class.

Classes

Classes are the "cookie cutters" that build objects. Just as a module groups subroutines in a package, a class groups methods in a package. Classes can also contain subroutines, submethods, and multimethods. Classes are significantly different than modules, though, primarily because they construct objects. Objects don't just define functionality, they also hold data. In Perl 5 objects were simply hashes bestowed with special powers by the bless built-in. Perl 6 objects can still be simple blessed data structures, but the default is now an object that hides the details of its internal representation--a true opaque object.

Attributes

Attributes are the data at the core of an opaque object. Other languages have called them instance variables, data members, or instance attributes. Attributes are declared with the has keyword, and generally have a "." after the sigil:

  class Heart::Gold {
      has int $.length;
      has int $.height is rw;
      has @.cargo;
      has %.crew;
      ...
  }

Remember how we said above that the . symbol was used with classes? This is another instance, the dot after the variable sigil indicates that the variable is an attribute of the class. Attributes aren't directly accessible outside the class, but inside the class they act just like ordinary variables.

  print $.length;
  $.length = 140;

Attributes also automatically generate their own accessor method with the same name as the attribute. Accessor methods are accessible inside or outside the class. By default, accessors are read-only, but the is rw property marks an accessor as read-write.

  my Heart::Gold $obj .= new()
  $value = $obj.height; # returns the value of $.height
  $obj.height = 90;     # sets the value of $.height
  $value = $obj.height  # Okay, is readable
  $obj.length = 20      # WRONG! $.length is not rw

Methods

Methods are similar to subroutines, but different enough to merit their own keyword, method. The most obvious differences are that they're invoked on an object (or class), and they pass their invocant (that is, the object or class on which they were invoked) as an implicit argument. The invocant is marked off from the other parameters in the list by a colon:

  method initiate_drive ($self: $power, $tea) {
      ...
  }

Methods topicalize their invocant, so it's always accessible as $_, even if the method doesn't include it in the parameter list. This is particularly handy since any method called without an explicit object defaults to $_:

  method shut_down ($drive) {
      if .safe {                # Same as $_.safe
          .powerdown($drive);   # Same as $_.powerdown($drive)
      }
      return .status;           # Same as $_.status
  }

Method declarations support the same syntax as subroutines for optional, named, variadic, and typed parameters, default values for parameters, properties on parameters, and return values. Method calls support positional and named argument passing just like subroutines. See Chapter 5 for more details on this syntax.

You can call a method in one of two ways. The standard method call is connected to the object with the . operator. Like we said, The . operator is like another way of saying "related to the class or object".

  $ship.shut_down($infinity);

An indirect object call is an alternative to the standard method call. This syntax looks like an ordinary subroutine call, except that the invocant is separated from the other arguments by a colon:

  shut_down($ship: $infinity);

The parentheses are optional unless the method call is ambiguous without them.

  shut_down $ship: $infinity;

Inheritance

Any class can inherit methods from another class using the is keyword in the class declaration. You may have noticed that this is the same keyword as compile-time properties. The fact that a class inherits from some other class is really just a trait of the inheriting class.

  use Ship;
  class Heart::Gold is Ship {
      ....
  }

Any class can inherit from multiple parent classes.

  class Heart::Gold is Ship is Improbable {
      ....
  }

Within a derived class, inherited attributes are accessible only through their accessor methods:

  class Ship {
      has $.height;
      has $.length;
      ...
  }
  
  class Heart::Gold is Ship {
      method dimensions ($self:){
          print "$self.length x $self.height \n";
      }
  }

Construction, Initialization, and Destruction

The default new method provided by the Object base class constructs and initializes opaque objects. It does this by calling bless, which calls the CREATE and BUILDALL methods. The CREATE method constructs an opaque object. The BUILDALL method calls the initializers for all inherited classes and finally the class's own initializer. BUILDALL actually calls the parent's BUILDALL method, which calls its parent's BUILDALL method, etc. The initializer for each class is BUILD. The default BUILD initializes the attributes of the object with named arguments to new, matching the name of the argument to the name of the attribute.

There are a number of ways to change the default object construction and initialization behavior. If you override new so that it passes a data structure as the first argument to bless, it will construct a traditional blessed hash object instead of calling CREATE to construct an opaque object:

  $class.bless({answer => '42'});

If you override the CREATE method you can alter the way objects are constructed. If you override the BUILDALL method you can change how the initializers for inherited classes are called. If you override the BUILD method you can change how the current class initializes objects and their attributes. Overriding BUILD will be common. Overriding CREATE and BUILDALL will be rare, since their default behavior is designed to handle everything from the simple opaque object to inheriting from classes written in other languages.

Object destruction traverses the inheritance hierarchy in the reverse order of object initialization. Objects are created from least derived to most derived and destroyed from most derived to least derived. The DESTROYALL method first calls the DESTROY method of the current class, and then calls the DESTROYALL method of the parent class (which calls its own DESTROY and then its own parent's DESTROYALL, etc). You will rarely need to define a DESTROY method, since the interpreter handles memory deallocation. It can be useful for class-specific cleanup, like closing a socket or filehandle.

Lexically Scoped Classes

Classes in Perl 6 are first class entities with entries in symbol tables or lexical scratchpads. This means classes can be lexically scoped, just like variables or subroutines:

  my class Infinite::Improbablity {
      ...
  }
  
  $drive = Infinite::Improbability.new();

A lexical class works just like any other class, but is accessible by name only within the lexical scope where it's defined.

Anonymous Classes

You can also define anonymous classes and create objects from them:

  $class = class {
     ...
  }
  
  $object = $class.new();

A class's block is a closure, just like every other block, so it has access to variables from its defining scope, no matter where it's actually used.

Roles

A role is a reusable unit of class code. Much like a module exports subroutines into your program or another module, a role exports methods and attributes into a class. If your first thought on reading this is "Isn't that just inheritance?", then welcome to a whole new world. Inheritance is one way to reuse code, but many relationships other than isa are possible. Various languages pick an alternative and provide syntax for it: Ruby has mixins, Java has interfaces, and some versions of Smalltalk have traits. Perl roles go a bit beyond all of them.

You define a role using the role keyword:

  role Hitchhiker {...}

You pull a role into a class using the does keyword:

  class Arthur does Hitchhiker {...}

Roles cannot instantiate objects directly. To create an object that makes use of a role, you make a new object from a class that uses that role:

  $person = Arthur.new(...);

Composition

Like classes, roles can define both attributes and methods:

  role Hitchhiker {
    has $.towel;
    method thumb_ride ($self: $ship) {...}
    ...
  }

Unlike classes, when you pull a role's methods and attributes into a class they aren't maintained in an inheritance hierarchy to be searched later. Instead, they are composed into the class almost as if they had been defined in that class. All methods defined in the role are accessible in the composed class, even if they wouldn't be inherited. All attributes defined in the role are accessible in the composed class by their direct $.name, not just by their accessor method.

One advantage of composition is that classes can reuse behavior, even if they have no connection that would justify an inheritance relation. Let's say you want to define two classes: Arthur and Ford. Arthur inherits from Human and has all the behaviors and qualities of a human creature. Ford, on the other hand, has the behaviors and qualities of a creature from Betelgeuse:

  class Arthur is Human does Hitchhiker {...}
  class Ford is Betelgeusian does Hitchhiker {...}

Inheritance makes sense in this case--the inherited classes are core, defining characteristics of the resulting class. But the Hitchhiker role isn't a defining part of Ford and Arthur--they weren't always hitchhikers. The role just adds some useful behavior to the class.

Mixins

In some situations you may want to add a role at run time instead of at compile time. Perhaps you want to choose different roles based on how the object is used, or perhaps the role's behavior shouldn't be available until part-way through the life of an object. The same does keyword adds roles at run time, but operates on an object instead of a class. In this example, Arthur starts as an ordinary human, and only adds the Hitchhiker role later in life:

  class Arthur is Human {...}

  $person = Arthur.new;
  $person.live_quietly until $vogon_ship.arrive;

  $person does Hitchhiker;
  $person.thumb_ride($vogon_ship);

Interfaces

An interface is a reusable unit that defines what methods a class should support, but doesn't provide any implementations for those methods. In Perl 6, interfaces are just roles that define only method stubs and no attributes. This example defines an interface for products shipped by the Sirius Cybernetics corporation:

  role Sirius::Cybernetics {
      method share {...}
      method enjoy {...}
  }

No matter whether the product is an elevator, a nutrimatic machine, or an automatic door, it must support the share and enjoy methods. Now, since these products are so very different, none will implement the methods in quite the same way, but you're guaranteed the products will be able to "Share and Enjoy" in one way or another (generally an irritating way).

Conflicts

Since a class pulls in roles by composition instead of inheritance, a conflict results when two roles both have a method with the same name. So, the Hitchhiker and Writer roles both define a lunch_break method (lunch breaks being vitally important in both the publishing and footslogging industries):

  role Hitchhiker {
      method lunch_break {
          .suck($.towel); 
          .drink($old_janx);
      }
      ...
  }

  role Writer {
      method lunch_break {
          my $restaurant = Jolly::Nice::Restaurant.new;
          .dine($restaurant);
      }
      ...
  }

If the Ford class does the Writer role as well as the Hitchhiker role, which kind of lunch break should he take? Since roles are composed without hierarchy or priority, both methods are equally valid choices. Rather than randomly selecting an implementation for you, Perl 6 simply requires you to choose one. There are several ways to do this. One is to define a method of the same name in the class itself. This method might simply call the method from one of the roles:

  class Ford does Hitchhiker does Writer {
      method lunch_break { .Writer::lunch_break(@_); }
  }

Or the method might select between the possible implementations based on one of the arguments or some condition in the object. This example checks the string value returned by the .location method to find out which lunch break is appropriate:

  class Ford does Hitchhiker does Writer {
      method lunch_break ($self: $arg) {
          given (.location) {
              when "Megadodo Office" { $self.Writer::lunch_break($arg); }
              when "Ship Cargo Hold" { $self.Hitchhiker::lunch_break($arg); }
          }
      }
  }

You can also get a finer-grained control over method conflict resolution using delegation syntax (explained in the next section). This example renames Hitchhiker's lunch_break method to snack in the composed class:

  class Ford does Hitchhiker handles :snackE<laquo>lunch_breakE<raquo> does Writer {...}

Delegation

Delegation is yet another possible relationship between an object and another body of code. Rather than pull methods into a class, you call methods in another object as if they were methods of the class. In Perl 6, delegation can be done in either a class or a role. A delegated object is simply an attribute defined in the class or role. The handles keyword specifies which methods of the delegated object will act as methods of the class. This example declares that any calls to the thumb_ride method on an object with the Hitchhiker role, will actually call the method on its $.thumb attribute:

  role Hitchhiker {
      ...
      has Electronic::Thumb $.thumb handles 'thumb_ride';
      ...
  }

The handles keyword accepts many variations in the syntax to delegate methods. You can pass it an array reference of multiple method names:

  has Electronic::Thumb $.thumb handles ['thumb_ride', 'sub_etha'];

Or a quoted list:

  has Electronic::Thumb $.thumb handles E<laquo>thumb_ride sub_ethaE<raquo>;

A pair in place of a string method name gives the method a different name in the class. This example declares a method named hitch in the class, but any calls to it are delegated to the thumb_ride method on the $.thumb object:

  has Electronic::Thumb $.thumb handles :hitchE<laquo>thumb_rideE<raquo>;

If the method name is given as a pattern, it's a wildcard delegation and all methods that match that pattern will be delegated to the attribute. This example delegates all methods that start with "thumb" to $.thumb:

  has Electronic::Thumb $.thumb handles /^thumb/;

If the method name is a substitution, it does wildcard method renaming. This example would delegate a method call to hitch_ride to a method named thumb_ride in $.thumb:

  has Electronic::Thumb $.thumb handles (s/^hitch/thumb/);

Private and Public

By default, all methods and attribute accessors are public methods, so they can be called anywhere. You can also declare private methods or accessors, which can be called only within the class where they're defined, or from certain trusted classes. A private method is declared with the my keyword at the start of the declaration.

  my method inaccessible ($self: $value) {...}

A private attribute is declared with an exclamation markin place of the dot (.) in the name:

  has $!hidden;

You call a private method or accessor with an exclamation mark in the call:

  $object.!hidden(42);

The attribute variable ($!name or $.name) is never accessible outside the class, whether the attribute is public or private.

At first glance this might look like nothing more than the "encapsulation by convention" of Perl 5. It's actually much more than that. The exclamation mark implicitly sets a private trait on the method or attribute. The encapsulation is enforced by the interpreter. An external call to a private method will fail as if the method simply didn't exist. External queries to the package symbol table for private methods also fail.

Only public methods are inherited by a derived class, but inherited public methods can call private methods from their own class. Private methods and attributes in a role are private to the composed class, as if they were defined in that class.

The one loophole in private methods is that a class can declare that it trusts certain other classes to allow those classes to access its private methods. Roles cannot declare a trusted class. In this example, the Friendly class declares that it trusts the Zaphod class:

  class Friendly {
      trusts Zaphod; # probably a bad idea, really
  }

Subroutines

You can define ordinary subroutines within a class or role. They cannot be invoked on an object with the $object.methodname syntax and will never pass an implicit invocant argument. They aren't inherited but can be pulled in with role composition. They're mainly useful for utility code internal to the class:

  class Answer::Young;
  
  has $.answer;
  ...
  sub is_valid ($value) {
      return 1 if 10 < $value < 42;
  }
  ...
  method set_answer ($new) {
      $.answer = $new if is_valid($new);
  }

Subroutines may be exported if the class also functions as a module.

Submethods

A submethod is declared like a method, but behaves more like a sub in that it's not inherited but can be pulled in with a role. Submethods are useful for inheriting interface without inheriting implementation--you can override a method from a parent class without inflicting the changes on any child classes.

The Frogstar::A class defines a set of methods and attributes for the Frogstar Scout robots:

  class Frogstar::A {
      has Laser::Beam     $.beam;
      has Antimatter::Ray $.ray;
      has Electron::Ram   $.ram;
      ...
      method zap   ($target) { $.beam.fire($target); }
      method shoot ($target) { $.ray.fire($target);  }
      method smash ($target) { $.ram.fire($target);  }
      ...
  }

In addition to methods for navigation, propulsion, etc. the Frogstar Scouts boast an astounding number of destructive methods (as is to be expected). The Frogstar::B class inherits all of Frogstar::A's methods and attributes, and also adds its own additional weaponry. Instead of defining a new method for the Zenon Emitter, the Frogstar Scout B overrides the smash method to use the emitter:

  class Frogstar::B is Frogstar::A {
      has Zenon::Emitter $.emitter;
      submethod smash ($target) { $.emitter.fire($target); }
  }

It still smashes the target, only faster, as you might expect from a newer model. Since the overridden method was declared as a submethod, it has no effect on the Frogstar Scout C which inherits from Frogstar::B:

  class Frogstar::C is Frogstar::B {...}
  ...
  $fighter = Frogstar::C.new(...);
  $fighter.smash($floor); # uses the Electron::Ram

Multiple Dispatch

In the previous chapter we mentioned multi subroutines. The multi keyword actually applies to any code object: subroutines, methods, or submethods. As we said before, multi allows you to define multiple different routines all with the same name but different signatures. This example dispatches to a variant of the lunch method depending on the types of the arguments:

  multi method lunch (Lunching::Friar $who, Megadodo::Office $location) {
      print "Jolly nice restaurant.";
  }

  multi method lunch (Hitchhiker $who, Cargo::Hold $location) {
      print "Towel again.";
  }

A member of the Lunching Friars of Voondon must always eat at a nice restaurant when he visits the offices of Megadodo Publications. A hitchhiker in a cargo hold, however, will just have to settle for the nutrient solution soaked into the corner of his towel.

A call to a multimethod has the same syntax as a call to a subroutine--the name of the routine followed by a list of arguments:

  lunch($zaphod, $where);

This call searches outward through its lexical, package, and global scopes for a matching name. If it finds a non-multi sub it makes an ordinary subroutine call. Otherwise it generates a list of multi subs, methods, or submethods with that name and dispatches to the closest matching signature.

You can also call a multimethod with an ordinary single-dispatch method call:

  $zaphod.lunch($where);

In this case, the call will only failover to multiple dispatch if it can't find a suitable method to call under single dispatch to $zaphod.

Operator Overloading

Operator overloading makes use of multiple dispatch. An operator is just a subroutine with special call syntax. Operators define the kind of syntax they use as part of their name: prefix, postfix, infix, circumfix, etc. This example overloads two operators that use the + symbol--one prefix operator and one infix operator:

  multi sub *prefix:+ (Time $a) {...}         # $x = +$y;
  multi sub *infix:+ (Time $a, Time $b) {...} # $x = $y + $z;

These operators are declared as multi subs with global scope, as most operators will be in Perl 6 (global is specified by the leading * in the name). They're multi so it's easy to add new behavior for new types of operands. They're global so that any operation anywhere with the defined operand types will find the right multi variant of the operator.