Category: Chapter 4. Classes

Class data variables are called attributes. They are declared with the has keyword. An attribute’s scope is defined via its twigil. As usual, the first character of the twigil indicates the type of the container (thus, a scalar, an array, or a hash). The second character is either . if a variable is public or ! for the private ones. An accessor will be generated by a compiler for the public attributes.

class Cafe {
has $.name;
has @!orders;
}

To create or instantiate an object of the class X, the constructor is called: X.new(). This is basically a method derived from the Any class (this is one of the classes on the top of the object system in Perl 6).

my $cafe = Cafe.new(
name => "Paris"
);

At this point, you can read public attributes.

say $cafe.name;

Reading from $.name is possible because, by default, all public fields are readable and a corresponding access method for them is created. However, that does not allow changing the attribute. To make a field writable, indicate it explicitly by adding the is rw trait.

Perl 6 defines the so-called submethods for classes. These are the methods which are not propagating to the subclass’s definition. The submethods may be either private or public, but they will not be inherited by the children.

With multiple inheritance, method resolution order is more important, as different base classes may have methods with the same name, or, for example, the two base classes have another common parent. This is why you should know the order of the base class now.

We have already seen elements of the object-oriented programming in Perl 6. Methods may be called on those variables, which do not look like real objects from the first view. Even more, methods may be called on constants.

The types that were used earlier (like Int or Str) are container types. Variables of a container type can contain values corresponding to some native representation. The compiler does all the conversion it needs for executing a programme. For example, when it sees 42.say, it calls the say method, which the Int object inherits from the top of the type hierarchy in Perl 6.

Perl 6 also supports object-oriented programming in its general understanding. If you are familiar with how to use classes in other modern programming languages, it will be easy for you to work with classes in Perl 6.

It is important that the result of the method search does not depend on which type was used to declare a variable. Perl 6 always will first use the methods belonging to the class of the variable, which is currently stored in the variable container. For example, return to the previous example and declare the variable $b to be one of type A, but still create an instance of B with B.new. Even in that case, calling $b.x will still lead to the method defined in the derived class.

my A $b = B.new;
$b.x; # B.x
$b.y; # A.y

Meta-methods (which also are available for every object without writing any code) provide information about the class details. In particular, to see the exact order in which method resolution will be executed, call the .^mro metamethod.

say $b.^mro;

In our example, the following order will be printed.

((B) (A) (Any) (Mu))

Of course, you may call the .^mro method on any other variable or object in a programme, regardless of whether it is an instance of the user-defined class, a simple variable, or a constant. Just get an idea of how this is implemented internally.

Now, after we have discussed inheritance, let us return to the private (or closed) methods. These methods may only be used within the class itself. Thus, you cannot call them from the programme that uses an instance of the class. Nor are they accessible in the derived classes. An exclamation mark is used to denote a private method.

The following example demonstrates the usage of a private method of a class. The comments in the code will help you to understand how it works.

class A {
# Method is only available within A
method !private {
say "A.private";
}
# Public method calling a private method
method public {
# You cannot avoid self here.
# Consider the '!' as a separator like '.'
self!private;
}
}
class B is A {
method method {
# Again self, but this the '.' this time.
# This is a public method.
self.public;
# This will be a compile-time error.
# self!private;
}
}
my $b = B.new;
$b.method; # A.private

The exclamation mark is actually part of the method name. So you can have both method meth and method !meth in the same class. To access them, use self.meth and self!meth, respectively: