Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl6 difference between bless and new

Tags:

oop

raku

class Singleton {
    # We create a lexical variable in the class block that holds our single instance.
    my Singleton $instance = Singleton.bless; # You can add initialization arguments here.
    method new {!!!} # Singleton.new dies.
    method instance { $instance; }
}

I find the above code which implement Singlelton , I am wondering what the difference between bless and new in Perl6 ?

my Singleton $instance = Singleton.bless; 


my Singleton $instance = Singleton.new; 
like image 435
smith Avatar asked Feb 26 '16 21:02

smith


2 Answers

Think of bless as infrastructure, whereas new is part of the (customizable) interface.

If you look at the implementation of class Mu (the root of the class system), you'll see that bless calls nqp::create, the low-level constructor, and then invokes BUILDALL, which walks the inheritance chain to invoke the appropriate BUILD (sub)methods to initialize the object. The default new in turn just calls bless.

So new calls bless calls BUILDALL calls BUILD. Normally, you should leave bless and BUILDALL alone and override new and BUILD for customization. Also note that the name new is just a convention: It's a regular method that doesn't do anything special besides calling bless.

like image 140
Christoph Avatar answered Oct 23 '22 22:10

Christoph


In simple terms, new is a full featured constructor and bless is a minimalist constructor.

To quote the doco on bless, bless is a ...

Lower-level object construction method than new. Creates a new object of the same type as the invocant, uses the named arguments to initialize attributes, and returns the created object. You can use this method when writing custom constructors:

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

... whereas new is a ...

Default method for constructing (create + initialize) new objects of a class. This method expects only named arguments which are then used to initialize attributes with accessors of the same name. Classes may provide their own new method to override this default.

New triggers an object construction mechanism that calls submethods named BUILD in each class of an inheritance hierarchy, if they exist. See the docmentation on object construction for more information.

See that documentation on object construction to get the full story, but the critical bit is;

Mu.new calls method bless on its invocant, passing all the named arguments. bless creates the new object and then calls method BUILDALL on it. BUILDALL walks all subclasses in reverse method resolution order (i.e. from Mu to most derived classes) and in each class checks for existence of a method named BUILD. If it exists, it is called, again passing all named arguments from method new to it.

In an earlier version of this answer, I stated that bless doesn't go through the class hierarchy calling submethod BUILD as described above - that was false. .bless does the same thing.

So, when do you use one over the other? If the default .new supplied by class Mu is not the constructor you want, you would declare a method new in your class which would call .bless to construct the object and then you would proceed to initialize attributes and perform those other tasks that the default .new doesn't do.

like image 5
Marty Avatar answered Oct 23 '22 22:10

Marty