问题
I am trying to write some classes with Perl 6 just for testing out Perl 6 classes and methods.
Here is the code:
class human1 {
method fn1() {
print "#from human1.fn1\n";
}
}
class human2 {
method fn1() {
print "#from human2.fn1\n";
}
}
my $a = human1.new();
my $b = human2.new();
$a.fn1();
$b.fn1();
print "now trying more complex stuff\n";
my $hum1_const = &human1.new;
my $hum2_const = &human2.new;
my $c = $hum2_const();
$c.fn1();
Essentially I want to be able to use either the human1
constructor or human2
constructor to be able to build $c
object dynamically. But I'm getting the following error:
Error while compiling /usr/bhaskars/code/perl/./a.pl6
Illegally post-declared types:
human1 used at line 23
human2 used at line 24
How do I create $c
using the function pointers to choose which constructor I use?
回答1:
I think this is a case of an LTA error. What I understand you want to achieve, is a lambda that will create a new human1
or human2
object for you. The way you do that is not correct, and the error it causes is confusing.
my $hum1_const = -> { human1.new };
my $hum2_const = -> { human2.new };
would be a correct way of doing this. Although, I would consider this a bit of an obfuscation. Since human1
and human2
are already constants, you can assign them to a variable, and then just call new
on that:
my $the_human = $condition ?? human1 !! human2;
my $c = $the_human.new;
$c.fn1;
Does that make sense?
回答2:
To get a “reference” to .new
you have to use the meta object protocol.
Either .^lookup, or .^find_method.
my $hum1-create = human1.^find_method('new');
That is still not quite what you are looking for, as methods require either a class object or an instance, as their first argument.
my $c = $hum1-create( human1 );
So you would probably want to curry the class as the first argument to the method.
my $hum1-create = human1.^find_method('new').assuming(human1);
my $c = $hum1-create();
Note that .assuming in this case basically does the same thing as
-> |capture { human1.^find_method('new').( human1, |capture ) }
So you could just write:
my $hum1-create = -> |capture { human1.new( |capture ) }
Or if you are never going to give it an argument
my $hum1-create = -> { human1.new }
Also you can store it in a &
sigiled variable, so you can use it as if it were a normal subroutine.
my &hum1-create = human1.^find_method('new').assuming(human1);
my $c = hum1-create;
来源:https://stackoverflow.com/questions/47994213/pointer-to-constructor-to-a-class-in-perl6