Re: Conceptual questions about Objects
On Saturday 05 April 2008 17:10:57 Larry Wall wrote: > On Fri, Apr 04, 2008 at 09:41:26PM -0500, John M. Dlugosz wrote: > > I suppose any object would do, it doesn't have to be "but undefined", or > > created using that Class{hash} syntax? > > Possibly. Haven't really thought through the ramifications, and it > feels a bit like the problem of confusing clone with new. It would > be pretty easy for idioms to arise that create a lot of useless > temporary objects. You can only sweep so much under the carpet of > "the optimizer could fix it"... > > In any case, the programmer really needs to keep straight when > an object is being used for its value vs when it's being used > for its type. Maybe that's not an issue here. Parrot-wise, right now that's somewhat more expensive than it should be. The carpet's not as large as I wish it were. (However it's possible not to require instantiating a new object or class for type checks, let's do that!) > We have another possible level of granularity there too, insofar as we > could trust a single multi or a proto that represents all multis in > its scope. Maybe a proto exported from within a class automatically > conveys trust to all normal multis (of the same name) declared the > import scope. Something about that I like. > > Also, since classes can be re-opened, anyone can grab trust from any > > class anyway, just by declaring a new method inside that class. > Well, sure. But whenever the programmer does that, the Perl 6 compiler > will automatically send email to the programmer's supervisor. :) If you mean "The World's Most Maintainable Programming Language", that was an April Fool's joke. -- c
Re: Conceptual questions about Objects
On Fri, Apr 04, 2008 at 09:41:26PM -0500, John M. Dlugosz wrote: > But see my q's to Audrey. Why does it need the qualified name if the same > class as $obj's declared type, We could conceivably relax that if $obj has a declared type. But on the other hand requiring the class name is pretty good documentation for what could be viewed as a violation of propriety, even if the other class has trusted us. It feels right to me from a huffman coding point of view, anyway. I'm not opposed to making the user jump through a few extra hoops for easily misunderstood constructs. But maybe you can argue me out of it. :) > and just how is that being parsed and/or implemented? expect_term -> post -> dotty: methodop -> name So it would be implemented as a semantic constraint in any case, not a syntactic one. >> See S12:680 and following for how to pass protoobjects representing >> partial construction without having to actually create intermediate >> objects. >> >> > OK, I didn't understand what that was about when I read it. Now I see it > as analogous to the base/member syntax in C++. > > I suppose any object would do, it doesn't have to be "but undefined", or > created using that Class{hash} syntax? Possibly. Haven't really thought through the ramifications, and it feels a bit like the problem of confusing clone with new. It would be pretty easy for idioms to arise that create a lot of useless temporary objects. You can only sweep so much under the carpet of "the optimizer could fix it"... In any case, the programmer really needs to keep straight when an object is being used for its value vs when it's being used for its type. Maybe that's not an issue here. >> Every class maintains its own concrete, which is of no business to >> anyone else, including derived classes. There is nothing like >> protected in Perl 6. The closest you can get to it is "trusts", >> and that's independent of class hierarchy. >> It is my understanding that even Bjarne thinks "protected" is a bad idea >> these days... >> > > OK, so what is the more general mechanism of providing different interfaces > to different sets of trusted consumers? There is the "protected interface" > that I document to explain how a derived class is to extend the > functionality, and it has access to things the caller doesn't, besides just > being able to override functions. If there is no special mechanism just > for derived classes, I suppose you must have something better in mind. > > For example, sometimes a particular module (namespace, whatever) might need > a special insider interface, because they work together. But not total > trust like its own implementation! Another contract, distinct from the > public interface contract. That's a good name for it: multiple contracts. > "trusted" hands out access to all private instance data, which is a special > case. Feels like it wants some form of delegation to me. On the other hand, contracts are generally expressed with roles in Perl 6, so maybe there could be some way of limiting trust to the granularity of a particular role's interface. > Oh, and in C++, friendship can be granted to a function as well as to a > class. I suppose there is less need in Perl 6 since a global function can > be written as a method and exported. But consider a function that operates > on two different objects; it can only be the method of one. I don't need > to make the whole other class trusted, just this one function. We have another possible level of granularity there too, insofar as we could trust a single multi or a proto that represents all multis in its scope. Maybe a proto exported from within a class automatically conveys trust to all normal multis (of the same name) declared the import scope. > Also, since classes can be re-opened, anyone can grab trust from any class > anyway, just by declaring a new method inside that class. Well, sure. But whenever the programmer does that, the Perl 6 compiler will automatically send email to the programmer's supervisor. :) Larry
Re: Conceptual questions about Objects
Many thanks. Larry Wall larry-at-wall.org |Perl 6| wrote: self!BaseName::attr should work, assuming BaseName trusts us. Because it is an accessor function, not a syntax to reference a variable in another scope. Got it. But see my q's to Audrey. Why does it need the qualified name if the same class as $obj's declared type, and just how is that being parsed and/or implemented? See S12:680 and following for how to pass protoobjects representing partial construction without having to actually create intermediate objects. OK, I didn't understand what that was about when I read it. Now I see it as analogous to the base/member syntax in C++. I suppose any object would do, it doesn't have to be "but undefined", or created using that Class{hash} syntax? Every class maintains its own concrete, which is of no business to anyone else, including derived classes. There is nothing like protected in Perl 6. The closest you can get to it is "trusts", and that's independent of class hierarchy. It is my understanding that even Bjarne thinks "protected" is a bad idea these days... OK, so what is the more general mechanism of providing different interfaces to different sets of trusted consumers? There is the "protected interface" that I document to explain how a derived class is to extend the functionality, and it has access to things the caller doesn't, besides just being able to override functions. If there is no special mechanism just for derived classes, I suppose you must have something better in mind. For example, sometimes a particular module (namespace, whatever) might need a special insider interface, because they work together. But not total trust like its own implementation! Another contract, distinct from the public interface contract. That's a good name for it: multiple contracts. "trusted" hands out access to all private instance data, which is a special case. Oh, and in C++, friendship can be granted to a function as well as to a class. I suppose there is less need in Perl 6 since a global function can be written as a method and exported. But consider a function that operates on two different objects; it can only be the method of one. I don't need to make the whole other class trusted, just this one function. Also, since classes can be re-opened, anyone can grab trust from any class anyway, just by declaring a new method inside that class. --John
Re: Conceptual questions about Objects
Ryan Richter ryan-at-tau.solarneutrino.net |Perl 6| wrote: You've declared method a twice here. According to S12, "You may write your own accessors to override any or all of the autogenerated ones." has $!a; method a { $!a } The variable is always really the $! form. I'm catching on.
Re: Conceptual questions about Objects
On Fri, Apr 04, 2008 at 07:01:32PM -0500, John M. Dlugosz wrote: > 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. Which is never a problem anyway, since private attributes are never, ever inherited, and are even off in their own namespace so they're completely invisible to a derived class. Suppose you derive: A -> B -> C Suppose B defines $!foo as a private attribute. This is invisible to C, to the extent that if A defines a public $.foo, it is visible in C. Private names are never allowed to clobber public names. > 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. self!BaseName::attr should work, assuming BaseName trusts us. >>> 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? As pointed out elsewhere, the spec does say, if you shake it hard enough. :) > 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? See S12:680 and following for how to pass protoobjects representing partial construction without having to actually create intermediate objects. >>> 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" 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. Well, the main reason there is no unary ! form is actually that prefix: already means something else in C-derived languages. :) >>> 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. Yes, there is no middle, by design. It's either concrete storage, hence non-virtual, or it's abstract and hence virtual. And even the class itself is encouraged to distinguish those usages, so it should use $!foo when it means the storage, and it should use $.foo when it means the concept, so that a derived class can override it. > 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. Eve
Re: Conceptual questions about Objects
You have completely lost me, John. What the heck are you asking? $obj.foo: calls public method "foo" on the object referenced by $obj. $.foo shorthand for calling "foo" on self (in scalar context). As I understand it, although I could be confused, these have absolutely nothing to do with whether or not there's a private "foo" attr, other than the convenience of being able to declare that the public "foo" method is actually an accessor for a private "foo" attr via the "has" syntax.
Re: Conceptual questions about Objects
On Friday 04 April 2008 16:56:44 Audrey Tang wrote: > In other words, there needs to be no real hard attribute "bar", no > matter if you call the "bar" method as self.bar(), $.bar(), or simply > $.bar. That's what I was trying to say with "uniform access principle", except that Audrey's version is much clearer. -- c
Re: Conceptual questions about Objects
John M. Dlugosz wrote: Seriously, Does this mean that the access of private attributes from trusted classes is a "different form"? And that's why you need the qualified syntax when I think it should not be necessary in all cases? Or should that passage really say "not in non-trusted classes, including derived classes"? It's a different form. Line 1207: (Private accessors are never virtual, and must be package qualified if called from a trusted scope other than our own. That is, it's either C or C<$obj!TrustsMe::attr().>) The reason is, I suspect, that what "trusts" does is putting a !TrustsMe::attr() into the trustee's scope, instead of somehow shadowing its own !attr() symbol. Cheers, Audrey
Re: Conceptual questions about Objects
Audrey Tang audreyt-at-audreyt.org |Perl 6| wrote: "Every Idiot declaration... " Sorry, must be a font problem Seriously, Does this mean that the access of private attributes from trusted classes is a "different form"? And that's why you need the qualified syntax when I think it should not be necessary in all cases? Or should that passage really say "not in non-trusted classes, including derived classes"? --John John M. Dlugosz wrote: OK, trust is not implicit on derived classes. Is that because there is no rule that says it is, or is there a mention of that somewhere in the official docs? There is. S12 Line 561: Every I declaration also declares a corresponding private I storage location, and the exclamation form may be used only in the actual class, not in derived classes. Cheers, Audrey
Re: Conceptual questions about Objects
John M. Dlugosz wrote: 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? No, there is no implicit trust, even of subclasses. For if that were the case, you would have a couple of problems at least: 1. A major advantage of having things private is that it lets subclasses not have to worry about implementation details of parent classes. Subclasses can declare their own private or public attributes or methods with the same names as private attributes or methods of their parents, and they won't conflict. If the parent adds new privates later, it doesn't have to worry about conflict with any subclasses. By contrast, typical (hash-based) Perl 5 classes have to deal with this problem all the time as all attributes and methods are actually public even if undocumented. 2. It would be very easy for anyone to defeat the security that the privacy is supposed to give, without the class being exposed having any say about it. -- Darren Duncan
Re: Conceptual questions about Objects
I understand your example. In fact, it further clarifies your earlier note. But that's not what I meant. I was thinking that access was through a variable, not understanding the real point of the syntax. Audrey Tang audreyt-at-audreyt.org |Perl 6| wrote: John M. Dlugosz wrote: That seems to be saying that using the method-call form is preferred, as it abstracts whether it is a real hard attribute or not. Er, it is not so. The $.foo notation is good not only for calling accessors, but also as a way to specify context when calling oneself's methods. Consider: class Foo { method bar ($x, $y) { ... } method baz ( $.bar: 1, 2; @.bar: 3, 4; } } Here we are simply typing $.bar as a shorthand of $(self.bar), and @.bar as @(self.bar), as well as supplying them with arguments; they do not mandate that there exists a "bar" attribute for our class. In other words, there needs to be no real hard attribute "bar", no matter if you call the "bar" method as self.bar(), $.bar(), or simply $.bar. Cheers, Audrey
Re: Conceptual questions about Objects
John M. Dlugosz wrote: OK, trust is not implicit on derived classes. Is that because there is no rule that says it is, or is there a mention of that somewhere in the official docs? There is. S12 Line 561: Every I declaration also declares a corresponding private I storage location, and the exclamation form may be used only in the actual class, not in derived classes. Cheers, Audrey
Re: Conceptual questions about Objects
Darren Duncan darren-at-darrenduncan.net |Perl 6| wrote: A method is defined within a role or class, as is an attribute. A private attribute can generally be referenced only by a method declared in the same role or class as said attribute. I think that's not right. A private attribute defined in a role becomes a private attribute of the composed class, so may be referred to from other roles or the main class definition. In contrast, a "my" variable inside the role is private to that role's block. Though it is put into the object's attribute list (the scope is per-instance), it has no name outside of the block. A method can reference its own role's/class's private attributes for any objects of that role/class, regardless of whether said object is the current method call's invocant or not. OK, taking "class" only, not "role". If a role or class is composed into another class or is subclassed, the (for example) subclass can not reference the private attributes of its parent class. As an exception to the above, if a particular class says that it "trusts" a particular other class (using "trusts Otherclass;" as a trait), then the trusted class can also reference the privates of the first class. OK, trust is not implicit on derived classes. Is that because there is no rule that says it is, or is there a mention of that somewhere in the official docs?
Re: Conceptual questions about Objects
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" 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
Re: Conceptual questions about Objects
John M. Dlugosz wrote: That seems to be saying that using the method-call form is preferred, as it abstracts whether it is a real hard attribute or not. Er, it is not so. The $.foo notation is good not only for calling accessors, but also as a way to specify context when calling oneself's methods. Consider: class Foo { method bar ($x, $y) { ... } method baz ( $.bar: 1, 2; @.bar: 3, 4; } } Here we are simply typing $.bar as a shorthand of $(self.bar), and @.bar as @(self.bar), as well as supplying them with arguments; they do not mandate that there exists a "bar" attribute for our class. In other words, there needs to be no real hard attribute "bar", no matter if you call the "bar" method as self.bar(), $.bar(), or simply $.bar. Cheers, Audrey
Re: Conceptual questions about Objects
On Friday 04 April 2008 16:31:56 John M. Dlugosz wrote: > chromatic chromatic-at-wgz.org |Perl 6| wrote: > > It shouldn't be. > So you are saying that... I was talking about syntax. > In that case, why allow the variable-name form at all? Because they're variables. Sure, they're instance variables, but like hearsay and conjecture are *kinds* of evidence, instance variables are kinds of variables. Sometimes it's nice to be able to assign to them, for example: method in_place_attribute_assignment ($.a, $.b, $.c); > >> Why keep the variable syntax? > > Uniform access principle. See also "Why Java programmers fetishize their > > IDEs, reason #482: autogeneration of metric boat-loads of > > accessors/mutators at just the click of a button." > > That seems to be saying that using the method-call form is preferred, as > it abstracts whether it is a real hard attribute or not. Since my > question was why keep the variable-name form, I think we are not > understanding each other. Yeah, I think you're asking the question backwards. Maybe you should ask instead "Why are there accessor methods for instance variables? Why not support only direct instance variable access?" > >> 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. > > That really depends on how much external syntax you want to change if you > > change the internal representation of an object. For me, that's > > approximately none. > I don't understand that sentence at all. Again, "invisibly by the > compiler" sounds like what you want. I'm still talking about syntax; I don't care for lvalue methods that look more like methods, not variables. Maybe that's a personal failing. I also could be completely misunderstanding what you're asking. I *am* supposed to be researching a J2EE/SOA article at the moment. -- c
Re: Conceptual questions about Objects
On Fri, Apr 04, 2008 at 06:31:56PM -0500, John M. Dlugosz wrote: > chromatic chromatic-at-wgz.org |Perl 6| wrote: > >It shouldn't be. > > > So you are saying that in the example of > >class C { > has $.a; > method a ($self:) You've declared method a twice here. has $.a is equivalent to has $!a; method a { $!a } The variable is always really the $! form. -ryan
Re: Conceptual questions about Objects
chromatic chromatic-at-wgz.org |Perl 6| wrote: It shouldn't be. So you are saying that in the example of class C { has $.a; method a ($self:) { side_effect(); return $self.a; } } # end C class D is C { method foo ($self:) { # ... $x = $self.a; # ... } } # end D that the variable-notation access in foo will call the explicit accessor method C::a? I suppose the use of $self.a in method a would be an infinite loop, and must be $self!a to work. In that case, why allow the variable-name form at all? Why keep the variable syntax? Uniform access principle. See also "Why Java programmers fetishize their IDEs, reason #482: autogeneration of metric boat-loads of accessors/mutators at just the click of a button." That seems to be saying that using the method-call form is preferred, as it abstracts whether it is a real hard attribute or not. Since my question was why keep the variable-name form, I think we are not understanding each other. 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. That really depends on how much external syntax you want to change if you change the internal representation of an object. For me, that's approximately none. I don't understand that sentence at all. Again, "invisibly by the compiler" sounds like what you want.
Re: Conceptual questions about Objects
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. 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? Or does it apply that constraint implicitly at run-time? If the former, note that in C++ it must be the identical class, NOT a derived class, even though that is simple to work around, because that is a conceptual point. A method is defined within a role or class, as is an attribute. A private attribute can generally be referenced only by a method declared in the same role or class as said attribute. A method can reference its own role's/class's private attributes for any objects of that role/class, regardless of whether said object is the current method call's invocant or not. If a role or class is composed into another class or is subclassed, the (for example) subclass can not reference the private attributes of its parent class. As an exception to the above, if a particular class says that it "trusts" a particular other class (using "trusts Otherclass;" as a trait), then the trusted class can also reference the privates of the first class. So "trusts" is useful when you have a good reason for certain classes to see each other's internals but that they are otherwise private; for example, say you're implementing a graph, and you have a separate class to define a graph node and the whole graph; those 2 classes are conceptually one feature, but are 2 classes because they provide 2 separable interfaces to users; the "trusts" lets you do the right thing interface-wise while remaining secure without contortions. Everything I just said ignores the fact that you can always additionally make public accessor methods for private attributes, to control/protect limited access to them for the general public. -- Darren Duncan
Re: Conceptual questions about Objects
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 } } 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. 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" 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. 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. 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
Re: Conceptual questions about Objects
On Friday 04 April 2008 13:47:40 John M. Dlugosz wrote: > But, it is also stated that in derived and trusted classes, and even in > the class itself, $.a is an accessor call? As opposed to $!a which is > the direct access to the attribute. Is this accessor different from the > function form used outside the class? It shouldn't be. > Why keep the variable syntax? Uniform access principle. See also "Why Java programmers fetishize their IDEs, reason #482: autogeneration of metric boat-loads of accessors/mutators at just the click of a button." > 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. That really depends on how much external syntax you want to change if you change the internal representation of an object. For me, that's approximately none. -- c