Wanting to run the recent class-attribute discussion[0] through the neural net of my friend, I described to him in detail how the current system with attributes works. He's kind of a Java guy, and though he liked the twigil distinction between private and public, he asked how to produce a 'protected'[1] attribute. A stylized IRC-ized version of the ensuing dialogue follows:
<masak> um, so 'protected' is when the deriving classes can see the attribute? <jonalv> yup <masak> that's what 'private' means in Perl 6. <jonalv> what? so there's only really 'public' and 'protected', but no 'private'? <masak> basically, yes. although 'protected' in Java is called 'private' in Perl 6. He then proceeded to tell me how in the real world, where all manner of people inevatibly derive from your base classes, having some attributes non-private (in the Java sense) simply wouldn't scale. Just to make things concrete, what we're talking about is this: $ perl6 > class A { has $!b = 42 } > class B is A { method foo() { say "LOL I can see your private attribute: $!b" > } } > B.new.foo LOL I can see your private attribute: 42 > class C is A { method foo() { $!b--; say "I can change it too, now it's $!b" > } } > C.new.foo I can change it too, now it's 41 Now, I've been taken aback by Perl 6's definition of private before[2], but I've never had any philosophical arguments for any particular position. My friend did. He said it gave away too much of the internal structure of the base class, essentially breaking encapsulation. I argued that that's always the case when you inherit, and that the problem is inheritance itself.[3] He said it caused people to use shortcuts when implementing things, because there's no barrier in place to 'behave' and use the proper interfaces. I countered that that's no different from any other abuse of an API. He then counter-countered that it *was* different, because as the base class author he's going to have to take all the crap from people having problems with the misbehaving derived classes, which pass for a base type anywhere in the code. He said that because of the lack of encapsulation along the inheritance relation, it would be possible for the authors of derived classes to break invariants of the base class. I was about to tell him about PRE and POST, but I think I got distracted by the thought that sometimes you might want to evaluate your PRE and POST block before/after *all* methods, not just one of them. (S04 actually has the answer: just put them in the class block itself[4]. Nice.) He said that even if someone miraculously got the derived class right (i.e. free of encapsulation breakages, shortcuts, and shattered invariants), it's still *philosophically* wrong to always leave out that much information to the derived classes. <masak> it's just the way Perl tends to do things. default-allow, unless the practice is *obviously* bad. <jonalv> well, it is, in this case. in the long run, it leads to brittle code. <masak> I think it's a question of Java defaulting to forbidding dangerous things, and Perl defaulting to allowing them. <jonalv> it's the wrong default. <masak> would you settle for a pragma? something like 'use OO::Private::Really;'? <jonval> um... I guess. but it's the wrong default. Thus, the discussion ended in a truce. :) But I'm left with a feeling of slight unease. Why *is* the default so leaky? What's the idea behind that? Won't it possibly cause a lot of encapsulation nightmares when people start to want to scale their OO applications? Just looking for some reassurance here. [0] <http://irclog.perlgeek.de/perl6/2010-03-22#i_2137068> [1] <http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html> [2] <http://irclog.perlgeek.de/perl6/2008-12-21#i_777747> [3] <http://www.c2.com/cgi-bin/wiki?InheritanceBreaksEncapsulation> [4] <http://perlcabal.org/syn/S04.html#Phasers> (The paragraph starting with 'Note:')