[Perl 6 page]

Class Declarations

If you look at all possible class contents declarations, they can be organized with the following parts:

scope declarator
my, our, has, empty
a ^ character
present or empty
routine
method, submethod, sub
sigil
$, etc.
twigil
. (dot), !, or empty
scope ^ routine sigil twigil example I meaning
my $ etc. my $var; S lexically scoped variable
our $ etc. our $var; S* package variable, useful as class attribute
my sub my sub foo () {...} S lexical subroutine
our / Ø sub sub foo () {...} S normal package subroutine
my method my method foo () {...} M private method
our / Ø method our method foo () {...}
method foo () {...}
M normal method
our / Ø ^ method method ^foo () {...} M class method
our / Ø submethod submethod foo () {...} M normal submethod
has $ etc. has $attrib; M private attribute with lexical alias
has $ etc. . has $.attrib; M public attribute
has $ etc. ! has $!attrib; M private attribute
my / our $ etc. . / ! my $.attrib;
my $!attrib;
our $.attrib;
our $!attrib;
M same as regular my/our variable, with accessors generated based on twigil.
my ^ method my method ^foo () {...} M Never mentioned in the Synopses, but meaning is clear as a private metaclass method.
our / Ø ^ sub sub ^foo () {...} M Not mentioned in Synopses, but meaning is clear: puts sub in package namespace with the metaclass methods.
Not Allowed
my / our / Ø ^
Ø
submethod my submethod foo () {...}
my submethod ^foo () {...}
x Never mentioned in the Synopses. Meaning would be clear, but it is pointless as there is no meaningful difference between a method and submethod in the metaclass.
any ^ $ etc. my $^foo; x syntax used for placeholder parameters, not here.
any ^ $ etc. . / ! my $^!foo; x syntax error — can’t have multiple twigils.
my ^ sub sub ^foo () {...} x not allowed. No point to using the ^ symbol.

What does it mean?

To understand what the various declarations mean, lets break it down into fundamentals, and look at what it actually does to the class object, scope, and other compile-time state.

routines

Let’s start with routines. A common sub, which will be our if you don’t say otherwise, will put a symbol in the package namespace and in the lexical scope. A sub declared as my will put it in the lexical scope only.

A normal method will put the symbol in the package namespace, just like a sub, so you could call it with the sub syntax and a package-qualified name if you wanted. Again, a regular method uses our, since that is the default if you don’t say otherwise. What makes it different from a sub is that the method is also added to the public dispatch table.

A submethod works the same as a method, except that it is not inherited. That is, a class will not copy them down from parent classes to populate its own dispatch table.

A metaclass method, defined using the ^ symbol, are actually added to the instance of the Class object, not to this class. So they don’t show up in the package namespace or the dispatch table. Instead, it gets put in the anonymous class derived from Class of which this class’s metaclass object is a singleton instance of. Assuming you knew the name (say, MyMetaClass) writing method ^foo is exactly the same as method MyMetaClass::foo, assuming that actually worked like ordinary subs and other package symbols (in reality, it would not add it to the dispatch table, just to the package namespace).

Those are the easy ones. We see that defining routines can affect the lexical scope (always), some package’s namespace, and some class’s dispatch table. Based on that, let’s try and understand the more exotic forms.

What does my method foo do? This defines a private method, and private methods are only called using a special syntax different from normal method calls. You can also have private submethods, and the only difference between and method and a submethod is that the latter is not inherited. So it follows that a private method is inherited and may be overridden by derived classes.

Putting the symbol in the package namespace is inconsistent with other uses of my vs our. The name does have to be known outside the block, since private methods can be called by derived classes, blocks for re-opened classes, and from classes that have been granted friendship. So the name and signature is stored away somewhere, just for that purpose. The easiest way to explain it is that there is a separate private dispatch table that holds the private methods and submethods. You always specify a private method via distinct syntax, so it knows to use the alternate table and include the check to see whether access is allowed from the calling point.

The Synopses S12 (as of version 62) does not make any mention of private metaclass methods, private submethods, or private metaclass submethods. That is, the forms my method ^foo, submethod ^foo, or my submethod ^foo. Does that mean they are not allowed?

Based on the above analysis, the meanings of these would be well formed. A private metaclass method would work just like a regular metaclass method but use the private dispatch table. Metaclass submethods would work just like metaclass methods but not inherit, or just like submethods but target the metaclass Class instead of the current class.

Are they useful? If you write a metaclass method ^foo, it might be good to have some helper functions to break it up into smaller parts, or share parts among several such methods. No different than for normal methods: you want private methods to help out. Just because you are making it a metaclass method doesn’t mean you won’t need to do that. On the other hand, you make something a submethod if you want to override a method for this class only, not for this class and derived classes. All the metaclass objects are distinct instances of the Class class (or rather anonymous classes derived from that just like how “but” and “does” do their stuff), and don’t form a hierarchy. So the difference between method and submethod is moot, and you have no reason to make a submethod in the metaclass.

The Synopses S12 (version 62) does not mention using ^ with sub. Is this meaningful? For a my sub, the sub is not “in” a class, so no. For an our sub, the name is added to the package namespace, so using ^ would put it in the metaclass object’s package instead. Later in this document I show an example of what that could do for you.

data

Now lets look at the meaning of various data item definitions.

The workings of my $x and our $x should be familiar. Both add $x to the lexical scope, and the latter adds it to the package namespace as well.

Now let’s look at has $!x. This allocates a slot for attribute $x. Like private methods, they are only accessible by using a distinct syntax. They are accessible only by this class and friend classes, and the blocks of re-opened classes. But they are not accessible to derived classes. The private accessor is a private submethod, which is hopefully inlined.

The syntax has $x is more confusing. It does the same as has $!x, and in addition puts $x into the lexical scope. So, referring to $x becomes a shortcut for $!x. But, that’s not a normal lexical variable that refers to a single location for the block. Rather, it’s a run-time lookup on the current object, $self!x.

If you use a dot instead of a !, you get everything mentioned before (a slot and private accessor) but in addition get a public accessor.

Finally, if you use my or our instead of has, but still use a . (dot) or ! twigil, you get the same accessors generated, but the underlying storage they access is not a slot but an ordinary my or our variable. This gives you one location for all instances, like a static data member in C++.

What do you do with it?

The chart above lists 17 different kinds of statements you can put in a class to declare things. That seems rather complicated, since it wouldn’t seem like there are that many different things you want to do! There is a lot of overlap in meaning, and different shades of meaning befitting a rich language that’s more like English than FORTRAN.

Ordinary Stuff — Fundamentals of OO

The most essential things you need to define a class are methods and instance data.

class Austere
 {
 has $!a;  # private attribute
 method foo ()
   {
     my $x = $!a;  # how to refer to instance data
     # how to access private instance data in a different object
     my Austere $obj = ...;
     my $y = $obj!a;  # use ! instead of . for private stuff
     return $x;
   }
 }

The has declaration allocates a slot in the instance, and creates a private accessor named a. How a slot actually works is opaque. It will vary by implementation and chosen storage mechanism. Only the generated private accessor knows how it is really done, using some implementation-specific system call or knowledge about how the instance works on that level.

The use of $!a looks casually like a variable with a twigil. It looks like that, and should “feel” like that because instance data should be easy to access just like local variables. But, it is actually not a variable name at all, but a private method call. $!a is short for $(self!a), which calls the self function to get the invocant, and then calls the a private method (in item context) on that. Hopefully, it will be efficiently inlined.

Notice that the $ sigil is not part of the name self, any more than it is part of the name a. It just hangs out there, providing a handy shortcut without doing anything special (unless you really needed to force item context). If you wanted to write it out the long way, you could use self!a and there is no sigil. Writing $self!a is actually wrong, unless you did in fact define a variable named $self. The built-in self keyword is a function, not a variable.

Because instance data is accessed using access methods, they are not like variables in that no sigil is part of the name. You could not define both has $!a; and has @!a; in the same class, because both generate my submethod a () is lvalue is inline { ... }. They are bare names, like functions, because they are functions. The most primitive access to a slot you can do is still through an accessor.

So given the class Austere above, which declares has $!a;, what would it mean to refer to @!a ? It would call self!a in list context, which is the same thing that happens when you write, e.g., ($x,$y) = self!a;.

As mentioned earlier, the private accessor generated is a private submethod. This means that it is only available to the class or things the class trusts, must be called using the private method syntax (the ! instead of a dot), and it is not inherited.

class Derived {...}  # forward reference

class Base
 {
  trusts Derived;
  has $!a;
 }

class Derived is Base
 {
 method explore ()
  {
   my $x;
   $x = $!a;  # ① No such private method in this class
   $x = self!Base::a;  # ② Still not allowed
   my $obj = Base.new;
   $x = $obj!a; # ③ Error, must qualify private name if not from Derived.
   $x = $obj!Base::a; # ④ Yes, allowed.
   my Base $b1 = $obj;
   $x = $b1!Base::a; # ⑤ Yes, allowed.
   $b1 = self;
   $x = $b1!Base::a; # ⑥ Yes, allowed.
  }
 }

The rules for accessing these non-inherited items can be discerned by looking at a fundamental case that is expected to work:

class Base
 {
 has $!a;
 method foo ()
  {
   ... $!a; ...
  }
 }

 class Derived is Base
 {
  ...
 }

my $x = Derived.new;
$x.foo;

Here, the public method foo is expected to still work, even though it is called on an object of a derived class. In the body of foo, the code sees the invocant with a statically declared type of Base, but a dynamic actual type of Derived. The reference to self!a should still mean the same thing. Since the object returned from the call to self is not a magical special case, we expect this to be the case for any object whose static type is Base. If the type is declared as Base, then the compiler can go straight to Base’s dispatch table and allow access. (It’s actually a little more complicated, as we’ll see later in the discussion of submethods.)

If the object is not declared to be of a particular type, then the run-time lookup will use the actual type of the object, and a is not in Derived’s dispatch table.

The use of the qualification syntax, Base::a, does not make the compiler look in a different class. The qualifier is there only to make it purposefully annoying to use, not to navigate scope as in C++. Other than being required to name it if the name is not the contained class, it does not change the meaning in any case.

So, cases 1 and 2 do not work because it looks for a in terms of a Derived instance. In case 1, it is declared to be Derived because that is what self returns. In case 2, it looks at the actual run-time type of the object. If you further derived from class Derived, added a different private method or submethod named a, and called explore on that object, then case 2 would resolve to that a, not the a in Base.

Case 4 works because the untyped variable $obj really holds an instance of type Base. Case 6 works because, even though it is the same object as in case 1, it is now statically typed as Base. Case 6 is the same as the call to foo, so it needs to work. That shows you how to access “inherited” private attributes, assuming you are already trusted: declare a variable of the matching type.

There may be 17 different things you can declare in a class, but Austere shows that you only need 2 of them to write true object-oriented and encapsulated code: private attributes and public methods. Private attributes (or rather, their private accessors) are only complicated if you want to access them from outside the same class they are defined for. They are private, not “protected” in the C++ sense.

Really Ordinary Stuff — No Classes Required

class Boring
 {
  my $a;
  our $b;
  my sub helper ()
   {   ...   }
  sub foo ()
   {
    helper;
    say $a, $b;
   }
 }

All the stuff in class Boring are things that could be anywhere, and are not related to making a class in the sense of the Fundamentals of OO discussed in the previous section. The good news is that you already know what these do, so that’s 4 more things out of the 17, that you don’t have to learn.

What’s interesting is what these can be used for in making a class. A sub may take arguments of the type of the class, so other than how they are called there is no real difference between them. A sub is most like a static member function in C++, in that it is still in the class’s scope and knows about private things, if only you had an object to operate on. Scoping the sub with my means it is only known to that block. It can’t be referred to from anyplace else in the program, regardless of trust or class relationships—it is a lexical scope issue.

Likewise, variables $a and $b can be used just like static data members in C++, in that all the code of the methods (and anything else in the block) can refer to them, and there is only one copy shared among all instances of the class. Note that $a is lexically scoped, and is only known within that block. That is stronger than “private”, and in fact lexical scoping can take care of most of the privacy issues in Perl 6, which is why there aren’t fancier protection levels.

The variable $b is also put in the package namespace, so it can be referred to as $Boring::b from outside that block. That is true for foo as well, as Boring::foo.

Unlike the static members in C++, these items in package scope are not automatically carried down to derived classes. The scope search for sub calling and other name lookup does not look in base classes. Rather, the inheritance behavior is only for methods invoked using the method dispatching syntax. So if you wanted $Boring::b or Boring::foo in a derived class, you would need to pull them down explicitly or qualify the names.

So, you can use ordinary variables and ordinary subs to support the code written for the public methods that define the class. Common code might readily be put in a sub, rather than a helper method. It might be handier to use a sub whose first argument is of the class type, rather than a private method, if you don’t want to be able to override it in a derived class, because the method-dispatch syntax will fail over to calling a sub if no such method is found. Private methods, on the other hand, need a special syntax.

class Blackguard
 {
  my method pm (Int $x) { ... }
  method bar (Int $x) { ... }
  my sub helper (Blackguard $this, Int $x) { ... }
  method foo ()
   {
   $.bar(5);  # call another public method
   $!pm(5);  # call a private method
   $.helper(5)  # calls helper(self,5)
   }
 }

Another reason to write a sub inside the class, rather than a method, is to avoid the issues with covariant parameter types. And a sub can be multi, so it has run-time dispatch based on types, just like a traditional method only more so. In fact, in CLOS everything is done that way, and there are no separate things called methods. A full treatment of this point will be in another article.

Private Methods

Public Accessors

Submethods

Metaclass methods

(or sub)

Orthodoxy

metaclass method delegation

A contradiction in S12<62>: Around line 477, it explains that

   our $count;
   method ^count { return $count }

Such a metaclass method is always delegated to the HOW object just as methods like .does are, so it’s possible to call this as Dog.count or $dog.count.

However, around line 1983 it illustrates

But Any gives you shortcuts to those:

   $obj.can("bark")
   $obj.does(Dog)
   $obj.isa(Mammal)

…In general, Any will delegate only those metamethods that read well when reasoning about an individual object. Infrastructural methods like .^methods and .^attributes are not delegated, so $obj.methods fails.

That is, metamethods are not automatically delegated by the dispatcher, but rather ordinary methods forward to the metamethod to enable that form of calling.

Over and over the document warns that you really shouldn’t use the shortcut form. So I’d suggest that the second way is right. If you want a shortcut to be available (if the method reads well when reasoning about an individual object) then write one, too.

Or, why define the ^foo form in the first place? As it explains earlier, any method can be called on the protoobject as long as it doesn’t try and access the undefined parts of the instance. So if you want to call $obj.count, then write method count, not method ^count.

You can also have a trait that generates the shortcut method as well, as syntactic sugar. That does not require any new language features.

forms not mentioned

Not every possible form is discussed or shown in example in S12<62>. I have included those that are both well-defined based on more generic discussion, and

private accessors

S12 doesn’t come out and say that the private accessors are submethods, just that they are “not inherited”. No other kind of “not inherited” thing is described, so if they are not submethods than even more is missing.

S12 doesn’t come out and directly say that bodies of subs, and all code inside the block of the class, is in the scope of the class for purposes of private method/submethod access.

details of “not inherited”

S12 does not go into detail about what is meant by “A submethod is called only when a method call is dispatched directly to the current class.” The details are compelled from basic principles, so I consider my description a clarification and not a proposal.