method bless

Documentation for method bless assembled from the following types:

class Mu

From Mu

(Mu) method bless

method bless(*%attrinit --> Mu:D)

Low-level object construction method, usually called from within new, implicitly from the default constructor, or explicitly if you create your own constructor. bless creates a new object of the same type as the invocant, using the named arguments to initialize attributes and returns the created object.

It is usually invoked within custom new method implementations:

class Point {
    has $.x;
    has $.y;
    multi method new($x$y{
        self.bless(:$x:$y);
    }
}
my $p = Point.new(-11);

In this case we are declaring new as a multi method so that we can still use the default constructor like this: Point.new( x => 3, y => 8 ). In this case we are declaring this new method simply to avoid the extra syntax of using pairs when creating the object. self.bless returns the object, which is in turn returned by new.

However, in general, implementing a customized new method might not be the best way of initializing a class, even more so if the default constructor is disabled, since it can make it harder to correctly initialize the class from a subclass. For instance, in the above example, the new implementation takes two positional arguments that must be passed from the subclass to the superclass in the exact order. That is not a real problem if it's documented, but take into account bless will eventually be calling BUILD in the class that is being instantiated. This might result in some unwanted problems, like having to create a BUILD submethod to serve it correctly:

class Point {
    has Int $.x;
    has Int $.y;
    multi method new($x$y{
        self.bless(:$x:$y);
    }
}
 
class Point-with-ID is Point {
    has Int $.ID  is rw = 0;
 
    submethod BUILD*%args ) {
        say %args;                # OUTPUT: «{x => 1, y => 2}␤» 
        for self.^attributes -> $attr {
            if $attr.Str ~~ /ID/ {
                $attr.set_valueself"*" ~ %args<x> ~ "-" ~ %args<y> ) ;
            }
        }
    }
}
 
my $p = Point-with-ID.new(1,2);
say $p.perl;
# OUTPUT: «Point-with-ID.new(ID => "*1-2", x => 1, y => 2)␤» 

In this code, bless, called within Point.new, is eventually calling BUILD with the same parameters. We have to create a convoluted way of using the $.ID attribute using the metaobject protocol so that we can instantiate it and thus serve that new constructor, which can be called on Point-with-ID since it is a subclass.

We might have to use something similar if we want to instantiate superclasses. bless will help us with that, since it is calling across all the hierarchy:

class Str-with-ID is Str {
    my $.counter = 0;
    has Int $.ID  is rw = 0;
 
    multi method new$str ) {
        self.blessvalue => $strID => $.counter++ );
    }
 
    submethod BUILD*%args ) {
        for self.^attributes -> $attr {
            if $attr.Str ~~ /ID/ {
                $attr.set_valueself%args<ID> ) ;
            }
        }
    }
}
 
say Str-with-ID.new("1.1,2e2").ID;                  # OUTPUT: «0␤» 
my $enriched-str = Str-with-ID.new("3,4");
say "$enriched-str{$enriched-str.^name}{$enriched-str.ID}";
# OUTPUT: «3,4, Str-with-ID, 1␤» 

We are enriching Str with an auto-incrementing ID. We create a new since we want to initialize it with a string and, besides, we need to instantiate the superclass. We do so using bless from within new. bless is going to call Str.BUILD. It will *capture* the value it's looking for, the pair value = $str> and initialize itself. But we have to initialize also the properties of the subclass, which is why within BUILD we use the previously explained method to initialize $.ID with the value that is in the %args variable. As shown in the output, the objects will be correctly initialized with its ID, and will correctly behave as Str, converting themselves in just the string in the say statement, and including the ID property as required.

For more details see the documentation on object construction.