user266003
user266003

Reputation:

A constructor with only 1 argument in Perl 6

I want to override new so that my class can be created only by passing one argument to the constructor, no more and no fewer.

class MyClass {
  has $.var1;

  method new($var1) {
    return MyClass.new(var1 => $var1);
  }
}

my $my_class1 = MyClass.new(33);
say $my_class1.var1;

The error is:

Too few positionals passed; expected 2 arguments but got 1
  in method new at test1.pl6:28
  in method new at test1.pl6:28
  in block <unit> at test1.pl6:33

What's up with it?

Upvotes: 6

Views: 298

Answers (1)

Christoph
Christoph

Reputation: 169673

Custom constructors need to call bless, ie

class MyClass {
    has $.var1;

    method new($var1) {
        return self.bless(var1 => $var1);
    }
}

There are a few things that can be improved, eg

  • one could add an explicit invocant parameter and use :U to make .new() fail when called on instance objects
  • the explicit return is superfluous - the last expression within the method will be returned anyway, and currently, it actually hurts performance
  • there's syntactic sugar for passing a named argument held in a variable of the same name

Putting it all together, we end up with

class MyClass {
    has $.var1;

    method new(MyClass:U: $var1) {
        self.bless(:$var1);
    }
}

As to where your error comes from:

Your method new is declared to take a positional argument (giving a total count of 2 expected arguments due to the implicit invocant), but the call MyClass.new(var1 => $var1) only passed a named one. Note that said method is the only .new() present in your class, so if the call had actually worked, you would have ended up with infinite recursion!

Upvotes: 10

Related Questions