Audrey Tang audreyt-at-audreyt.org |Perl 6| wrote:
John M. Dlugosz wrote:
A method can refer to private attributes etc. in other objects than
self. This is unlike Smalltalk and like C++. Which objects? Obviously,
those that _have_ them in the first place.

Correct, though those classes also has to trust the calling class:

class MyClass { has $!attr; trusts YourClass }
class YourClass {
    method foo (MyClass $obj) {
        $obj!MyClass::attr; # Access to $obj's private attr
    }
}

So, do classes trust their derived classes by default? Is trust itself inherited?

In this example, as in S12, why do you have to specify the MyClass:: prefix? I thought you would only need this to refer to a specific class in the ISA list and not necessarily the one defined in or visible in the declared class.

That is, a derived class, assuming it was trusted, could use $self!BaseName::attr to prevent confusion with something named self!attr that ordinarily hides it.

And a syntax question for you: Above, I just assumed $self is the explicitly-named invocant. How do you access the attribute if using the self keyword, which does not have a sigil? If it has $!attr and has @!attr, that is important. I realize this is not an issue when using method calls (including accessor functions) on self.


Does the variable used as the invocant, or return value if it is an expression,
> have to be statically typed as being of the identical class?

The $obj above must be evaluated to an object of class MyClass.

AFAICS, the spec doesn't really say if a derived class needs to explicitly trust YourClass for it to be used this way:

class MyDerivedClass is MyClass {};
YourClass.foo(MyDerivedClass.new(attr => 1)); # Not sure if this works.
"the spec doesn't say" hence my confusion. So will Larry rule on that, or should we discuss it in detail, or should I just make up something in my proposed doc edit?

If your example does work, it means that in general the BUILD can comb arguments out for each class in the hierarchy, rather than only being allowed to specify arguments to defined constructors for the base classes, as in C++. Is that good or bad? Just how would you say the latter, anyway?

If class C { has $.a; ... }, then I understand that members may refer to
$.a directly but outside of the scope of members defined in the class
they can only be reached by accessors, a() as a method call.

Well, $.a is exactly the same as $(self.a) -- see S12/"are just shorthands of C<self.foo>" for the definition.

Methods in class C may call $!a, which is the private accessor method.
Outside the scope, private methods of class C are invisible.

OK, I think I'm beginning to see. $.x is not "variable-like", but a shortcut for $(self.x()), and always is. You don't name an object with this form, ever, as it only works on self. That is why the ! forms don't have a "unary form". It could certainly be explained better in the document. Your retelling is already helpful.



But, it is also stated that in derived and trusted classes, and even in
the class itself, $.a is an accessor call?

Well, $.a is merely shorthand for $(self.a) so derived classes can call it just fine. However in trusted classes, $.a wouldn't make much sense,
as you need to use either $obj.a or $obj!YourClass::a there.

Is this accessor different from the
function form used outside the class? Why keep the variable syntax?

Because it's jolly convenient, especially in interpolated strings, I suppose:

say "My position is $.x - $.y - $.z";

I'm getting a picture of 3 forms of access: Really direct, direct but
asking the class to access it rather than knowing how storage works, and
indirect that may involve your own code to do other things besides just
get/set the attribute. But I think the middle one can be handled
invisibly by the compiler -- it's no different from a tied hash.

The middle one is not that different from the first one, because from an implementation viewpoint, once YourClass trusts MyClass, then code in MyClass might as well have knowledge about how the storage works.
But it looks like there is no middle one.

Besides "how the storage works", I'm thinking of the multiple-base composition issues. The attribute may be stored in different places depending on the concrete type, and the method is called on a type derived from the one it is written in.


How private is private? I wonder if what you've called private things
are really more like "protected" in C++ (accessible by the derived
class) and that 'my' attributes are really private, as are submethods.
It's all confused. Who is allowed to access what?

No, private methods are not accessible from derived classes, unless the base class explicitly trusts them -- See L12/"the exclamation form may be used only in the actual class, not in derived classes".

Cheers,
Audrey



Reply via email to