Carl (>>), sorear (>):
>> * It has been decided that attribute slots of the type $!foo are only
>> allowed *syntactically* within the class block that declares them.
>> (The exception to this, I guess, is the 'trusts' directive.) But this
>> means that something like this anonymous method
>>
>>     my $reveal-foo = method { say $!foo }
>>
>> isn't allowed. I think that's good, because it would provide a very
>> easy way to break encapsulation of an object; just call
>> $object.$reveal-foo() on it.
>
> There is no $!foo.  There is only $!Class::foo, and $!foo is a lexically
> scoped alias to it.  This is necessary to allow privacy from your children
> to work:
>
> class Class {
>    has $!foo;  # the mere existance of $!foo is an implementation detail
> }
>
> class SubClass is Class {
>    has $!foo;  # hey why doesn't this work?
> }
>
> So $reveal-foo can't be defined because $!foo isn't even in scope.

Thanks, that's an excellent way to explain this. It also provides the
answer to this whole thread:

    class A {
        has $!x;
    }

    class B {
        has $!x;
        method foo { say $!x } # really 'say $!B::x'
    }

    my $b-foo = B.^can("foo");
    A.new( :x(42) ).$b-foo(); # doesn't work, can't access $!B::x from A

This solution is a fourth one that I didn't see, and the first one that I like:

d. Disallow illegally accessing a private attribute slot that isn't yours.

It also incidentally answers a random thought I had today after
posting my original email: "Hey, jnthn talked about implementing
attribute accesses as array accesses rather than hash accesses -- how
the heck will that work if methods can be detached and re-attached to
objects of a different class?" With $!foo really meaning
$!MyClass::foo it makes a lot more sense.

// Carl

Reply via email to