Rafael Garcia-Suarez asked:

> Damian Conway <[EMAIL PROTECTED]> wrote:
>
>>There are in fact *two* types associated with any Perl variable
>
> How does it work regarding inheritance and polymorphism ?
> E.g. consider
>   my @a is Set of Apple;
>   my @b is Basket of Fruit;
> with Apple isa Fruit, and Basket is a Set.
>
> I assume I can use @a or @b where the expected type is:
>
>                       @a  @b
>     Set               ok  ok
>     Set of Fruit      ok  ok
>     Set of Apple      ok  no(?)
>     Basket            no  ok
>     Basket of Fruit   no  ok
>     Basket of Apple   no  no(?)

All of these seem to make the same incorrect assumption: that the
implementation type specifies what a variable evaluates to.
It doesn't. The storage type does that.

So, saying:

    my @a is Set of Apple;

doesn't make C<@a> evaluate to an object of class C<Set of Apple>.
Nor does it define that @a can store a C<Set of Apple>.

We *can* answer your real question (about inheritance and compound types), but
we have to start with the right declarations:

    my  $a  returns    Set of Apple;
    my  $b  returns Basket of Fruit;

or:

    my     Set of Apple  $a;
    my  Basket of Fruit  $b;

and a generic assignment:

    $c = $a;
    $c = $b;

Now we can fill in your list (which is somewhat expanded):


       Assignment                    OK?    Because...
       ======================        ===   ===============================

       my Set $c = $a                ok     $c's type:  Set (of Object)
                                                         ^         ^
                                                         |         |
                                            $a's type:  Set  of  Apple



       my Set $c = $b                ok     $c's type:   Set  (of  Object)
                                                          ^          ^
                                                          |          |
                                            $b's type:  Basket of  Fruit



       my Set of Fruit $c = $a       ok     $c's type:  Set of Fruit
                                                         ^       ^
                                                         |       |
                                            $a's type:  Set of Apple



       my Set of Fruit $c = $b       ok     $c's type:   Set   of Fruit
                                                          ^         ^
                                                          |         |
                                            $b's type:  Basket of Fruit


       my Set of Apple $c = $a       ok     $c's type:  Set of Apple
                                                         ^       ^
                                                         |       |
                                            $a's type:  Set of Apple


       my Set of Apple $c = $b       no     $c's type:   Set   of Apple
                                                          ^         X
                                                          |         |
                                            $b's type:  Basket of Fruit


       my Basket $c = $a             no     $c's type:  Basket (of Object)
                                                          X          ^
                                                          |          |
                                            $a's type:   Set  of   Apple


       my Basket $c = $b             ok     $c's type:  Basket (of  Object)
                                                          ^           ^
                                                          |           |
                                            $b's type:  Basket  of  Fruit


       my Basket of Fruit $c = $a    no     $c's type:  Basket of Fruit
                                                          X         ^
                                                          |         |
                                            $a's type:   Set   of Apple


       my Basket of Fruit $c = $b    ok     $c's type:  Basket of Fruit
                                                           ^         ^
                                                           |         |
                                            $b's type:  Basket of Fruit


       my Basket of Apple $c = $a    ok     $c's type:  Basket of Apple
                                                          ^         ^
                                                          |         |
                                            $a's type:  Basket of Apple


       my Basket of Apple $c = $b    no     $c's type:   Set   of Apple
                                                          ^         X
                                                          |         |
                                            $b's type:  Basket of Fruit


             ^
As usual the | arrow between two classes represents the C<.isa> relationship.

                         X
And I've used the symbol | to represent the complementary C<.isnta>
relationship.


In other words, to be able to assign a C<Righty> object to a C<Lefty> variable
(or use a C<Righty> in any other context where a <Lefty> is expected):

    my Lefty $var = Righty->new();

each component of type C<Righty> must be in a valid C<.isa> relationship to
the corresponding element of C<Lefty>. In other words:

    my X of Y of Z $var = (A of B of C)->new();

is only permitted if:

    A.isa(X) &&
    B.isa(Y) &&
    C.isa(Z)


Hope that helps.

Damian



Reply via email to