问题
I'm reading a spreadsheet looking for different structures. When I tried the following using Moose it seems to do what I want. I could create different types of objects, assign this to the found member and dump the Cell instance for review.
package Cell
{
use Moose;
use Moose::Util::TypeConstraints;
use namespace::autoclean;
has 'str_val' => ( is => 'ro', isa => 'Str', required => 1 );
has 'x_id' => ( is => 'ro', isa => 'Str', ); # later required => 1 );
has 'color' => ( is => 'ro', isa => 'Str', );
has 'border' => ( is => 'ro', isa => 'Str', );
has 'found' => ( is => 'rw', isa => 'Sch_Symbol|Chip_Symbol|Net', );
1;
}
If I try to do the same in Perl 6 it fails to compile.
class Cell {
has Str $.str_val is required;
has Str $.x_id is required;
has Str $.color;
has Str $.border;
has Sch_Symbol|Chip_Symbol|Net $.found is rw
}
Malformed has at C:\Users\Johan\Documents/moose_sch_3.pl6:38 ------> has Sch_Symbol'<'HERE'>'|Chip_Symbol|Net $.found is rw
How can I do this in Perl 6?
回答1:
You could use where
has $.found is rw where Sch_Symbol|Chip_Symbol|Net;
or define new type by subset
subset Stuff where Sch_Symbol|Chip_Symbol|Net;
class Cell {
has Str $.str_val is required;
has Str $.x_id is required;
has Str $.color;
has Str $.border;
has Stuff $.found is rw;
}
回答2:
You probably want them to do a common role and specify that as the type
role Common {}
class Sch-Symbol does Common {…}
…
class Cell {
…
has Common $.found is rw;
}
Or you will have to use a where
constraint
class Cell {
…
has $.found is rw where Sch-Symbol|Chip-Symbol|Net;
}
You could also create a subset to wrap the where
constraint.
subset Common of Any where Sch-Symbol|Chip-Symbol|Net;
class Cell {
…
has Common $.found is rw;
}
Note that a where
constraint is slower than using a common role.
回答3:
Here is a fully working implementation of the subset/where
solution mentioned by Brad Gilbert in his answer. This includes one example for each of the classes in Common
and also one example that shows what happens when type constraints aren't met:
#!/bin/env perl6
class Sch-Symbol { has Str $.name }
class Chip-Symbol { has Num $.num }
class Net { has Int $.id }
subset Common of Any where Sch-Symbol|Chip-Symbol|Net;
class Cell {
has Str $.str_val is required;
has Str $.x_id is required;
has Str $.color;
has Str $.border;
has Common $.found is rw;
}
my $str_val = 'foo';
my $x_id = 'bar';
my @founds = (
Net.new(:42id), # will work
Sch-Symbol.new(:name<baz>), # will work
Chip-Symbol.new(num => 1E101), # will work
42, # won't work
);
for @founds -> $found {
my $cell = Cell.new(:$str_val, :$x_id, :$found);
dd $cell;
}
Assuming this is in the file test.p6
, when we run perl6 test.p6
we get:
Cell $cell = Cell.new(str_val => "foo", x_id => "bar", color => Str, border => Str, found => Net.new(id => 42)) Cell $cell = Cell.new(str_val => "foo", x_id => "bar", color => Str, border => Str, found => Sch-Symbol.new(name => "baz")) Cell $cell = Cell.new(str_val => "foo", x_id => "bar", color => Str, border => Str, found => Chip-Symbol.new(num => 1e+101)) Type check failed in assignment to $!found; expected Common but got Int (42) in submethod BUILDALL at test.p6 line 9 in block <unit> at test.p6 line 28
来源:https://stackoverflow.com/questions/49660447/how-do-i-declare-a-class-attribute-as-a-union-of-class-names