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