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:')

Reply via email to