How do I declare a class attribute as a union of class names?

前端 未结 3 1902
别那么骄傲
别那么骄傲 2021-01-12 08:41

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, as

相关标签:
3条回答
  • 2021-01-12 08:46

    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;
    }
    
    0 讨论(0)
  • 2021-01-12 08:57

    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.

    0 讨论(0)
  • 2021-01-12 09:06

    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
    
    0 讨论(0)
提交回复
热议问题