如何将类属性声明为类名联合?

时间:2018-04-04 21:07:15

标签: perl6

我正在阅读寻找不同结构的电子表格。当我尝试以下使用Moose时,它似乎做了我想要的。我可以创建不同类型的对象,将其分配给找到的成员 并转储Cell实例以供审核。

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;
}

如果我尝试在Perl 6中执行相同的操作,则无法编译。

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

如何在Perl 6中执行此操作?

3 个答案:

答案 0 :(得分:7)

您可能希望他们做一个共同的角色,并将其指定为类型

role Common {}
class Sch-Symbol does Common {…}
…

class Cell {
  …
  has Common $.found is rw;
}

或者你必须使用where约束

class Cell {
  …
  has $.found is rw where Sch-Symbol|Chip-Symbol|Net;
}

您还可以创建一个子集来包装where约束。

subset Common of Any where Sch-Symbol|Chip-Symbol|Net;

class Cell {
  …
  has Common $.found is rw;
}

请注意,where约束比使用公共角色要慢。

答案 1 :(得分:5)

以下是Brad Gilbert在his answer中提到的subset/where解决方案的完整工作实现。这包括Common中每个类的一个示例,以及一个显示未满足类型约束时会发生什么的示例:

#!/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;
}

假设这是在test.p6文件中,当我们运行perl6 test.p6时,我们得到:

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

答案 2 :(得分:4)

您可以使用where

has $.found is rw where Sch_Symbol|Chip_Symbol|Net;

或按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;
}