Categories
Posts in this category
- Current State of Exceptions in Rakudo and Perl 6
- Meet DBIish, a Perl 6 Database Interface
- Perl 6 Hackathon in Oslo: Be Prepared!
- Perl 6 Hackathon in Oslo: Report From The First Day
- Perl 6 Hackathon in Oslo: Report From The Second Day
- Rakudo Hack: Dynamic Export Lists
- SQLite support for DBIish
- Upcoming Perl 6 Hackathon in Oslo, Norway
- A shiny perl6.org site
- Creating an entry point for newcomers
- An offer for software developers: free IRC logging
- Sprixel, a 6 compiler powered by JavaScript
- Announcing try.rakudo.org, an interactive Perl 6 shell in your browser
- Another perl6.org iteration
- Blackjack and Perl 6
- Why I commit Crud to the Perl 6 Test Suite
- This Week's Contribution to Perl 6 Week 5: Implement Str.trans
- This Week's Contribution to Perl 6
- This Week's Contribution to Perl 6 Week 8: Implement $*ARGFILES for Rakudo
- This Week's Contribution to Perl 6 Week 6: Improve Book markup
- This Week's Contribution to Perl 6 Week 2: Fix up a test
- This Week's Contribution to Perl 6 Week 9: Implement Hash.pick for Rakudo
- This Week's Contribution to Perl 6 Week 11: Improve an error message for Hyper Operators
- This Week's Contribution to Perl 6 - Lottery Intermission
- This Week's Contribution to Perl 6 Week 3: Write supporting code for the MAIN sub
- This Week's Contribution to Perl 6 Week 1: A website for proto
- This Week's Contribution to Perl 6 Week 4: Implement :samecase for .subst
- This Week's Contribution to Perl 6 Week 10: Implement samespace for Rakudo
- This Week's Contribution to Perl 6 Week 7: Implement try.rakudo.org
- What is the "Cool" class in Perl 6?
- Report from the Perl 6 Hackathon in Copenhagen
- Custom operators in Rakudo
- A Perl 6 Date Module
- Defined Behaviour with Undefined Values
- Dissecting the "Starry obfu"
- The case for distributed version control systems
- Perl 6: Failing Softly with Unthrown Exceptions
- Perl 6 Compiler Feature Matrix
- The first Perl 6 module on CPAN
- A Foray into Perl 5 land
- Gabor: Keep going
- First Grant Report: Structured Error Messages
- Second Grant Report: Structured Error Messages
- Third Grant Report: Structured Error Messages
- Fourth Grant Report: Structured Error Messages
- Google Summer of Code Mentor Recap
- How core is core?
- How fast is Rakudo's "nom" branch?
- Building a Huffman Tree With Rakudo
- Immutable Sigils and Context
- Is Perl 6 really Perl?
- Mini-Challenge: Write Your Prisoner's Dilemma Strategy
- List.classify
- Longest Palindrome by Regex
- Perl 6: Lost in Wonderland
- Lots of momentum in the Perl 6 community
- Monetize Perl 6?
- Musing and the future of feather and the Pugs repository
- Musings on Rakudo's spectest chart
- My first executable from Perl 6
- My first YAPC - YAPC::EU 2010 in Pisa
- Trying to implement new operators - failed
- Programming Languages Are Not Zero Sum
- Perl 6 notes from February 2011
- Notes from the YAPC::EU 2010 Rakudo hackathon
- Let's build an object
- Perl 6 is optimized for fun
- How to get a parse tree for a Perl 6 Program
- Pascal's Triangle in Perl 6
- Perl 6 in 2009
- Perl 6 in 2010
- Perl 6 in 2011 - A Retrospection
- Perl 6 ticket life cycle
- The Perl Survey and Perl 6
- The Perl 6 Advent Calendar
- Perl 6 Questions on Perlmonks
- Physical modeling with Math::Model and Perl 6
- How to Plot a Segment of a Circle with SVG
- Results from the Prisoner's Dilemma Challenge
- Protected Attributes Make No Sense
- Publicity for Perl 6
- PVC - Perl 6 Vocabulary Coach
- Fixing Rakudo Memory Leaks
- Rakudo architectural overview
- Rakudo Rocks
- Rakudo "star" announced
- My personal "I want a PONIE" wish list for Rakudo Star
- Rakudo's rough edges
- Rats and other pets
- The Real World Strikes Back - or why you shouldn't forbid stuff just because you think it's wrong
- Releasing Rakudo made easy
- Set Phasers to Stun!
- Starry Perl 6 obfu
- Recent Perl 6 Developments August 2008
- The State of Regex Modifiers in Rakudo
- Strings and Buffers
- Subroutines vs. Methods - Differences and Commonalities
- A SVG plotting adventure
- A Syntax Highlighter for Perl 6
- Test Suite Reorganization: How to move tests
- The Happiness of Design Convergence
- Thoughts on masak's Perl 6 Coding Contest
- The Three-Fold Function of the Smart Match Operator
- Perl 6 Tidings from September and October 2008
- Perl 6 Tidings for November 2008
- Perl 6 Tidings from December 2008
- Perl 6 Tidings from January 2009
- Perl 6 Tidings from February 2009
- Perl 6 Tidings from March 2009
- Perl 6 Tidings from April 2009
- Perl 6 Tidings from May 2009
- Perl 6 Tidings from May 2009 (second iteration)
- Perl 6 Tidings from June 2009
- Perl 6 Tidings from August 2009
- Perl 6 Tidings from October 2009
- Timeline for a syntax change in Perl 6
- Visualizing match trees
- Want to write shiny SVG graphics with Perl 6? Port Scruffy!
- We write a Perl 6 book for you
- When we reach 100% we did something wrong
- Where Rakudo Lives Now
- Why Rakudo needs NQP
- Why was the Perl 6 Advent Calendar such a Success?
- What you can write in Perl 6 today
- Why you don't need the Y combinator in Perl 6
- You are good enough!
Thu, 09 Sep 2010
Protected Attributes Make No Sense
Permanent link
In C++, you can declare an attribute or a method as "protected". Which means that it is private, but subclasses can still access them.
This makes just as much sense as saying you only get access to these attributes if you wear a funny yellow hat.
I'll try to explain why.
Encapsulation has the advantage that you can change the implementation of a class without changing the API. If you write a library, that means you don't break your user's code if you change some internals.
However your users can not only instantiate your classes, but they can also inherit from them. Which means they can put a funny yellow hat on. There is no restriction as to who can inherit from your classes. Which makes protected attributes part of the public interface.
So, if you want to change the implementation of a class, you can't change how a protected attribute or method works, and what data it stores. If you do, you break all subclasses. Which not only exist in your own source tree, but in your user's source tree too. If you think that changing the implementation will also change protected attributes or methods, make them private.
So if protected methods are essentially part of the public API anyway, why not declare them as public? Why require your user to wear a funny yellow hat (aka declare an inheritance relation) while using your class? There is no good reason.
When seasoned C++ programmers hear that, they often respond with "but if I declare my private data as private a subclass doesn't have access to it! How can it work properly?". The answer is simple: You must provide a sufficiently powerful public API. Your users will be grateful.
One more thing: people often come up with an analogy to the real world, and claim that your kids also have access to your house or flat. This analogy is broken, because in the real world the parents have to take actions to get children (or give somebody the same status as your children). In the programming world, every outsider can write a child class of your classes.
(The reason I posted this in the Perl 6 section of this blog is that Perl 6 has no protected attributes. Which has spawned many interesting discussions, which were the precursor to this blog post.)
Comments / Trackbacks:
Trackback URL:
/blog-en/perl-6/protected-attributes-make-no-sense.trackback
Rachel Blum wrote
Actually, they sometimes do make sense. Especially as so-called 'customization points'.
This allows you to override certain internal functionality of your class that is only called by the class and its descendants.
Simple example: You have a FetchData class that gets data from a remote resource. One of the customization points is OnConnectionEstablished - different subclasses can take different actions whenever a connection is established. (Because they might need to send certain handshake/config info, whatever)
It makes no sense to call that outside of the class, but derived classes need access to override - hence, protected. (The main issue here is that C++ conflates inheritance and access protections)
Now, I'd make the point that protected and private members in C++ are a disaster for introspective testing (since you can't actually introspect...), but that's a different kettle of fish
Claudio wrote
protected in Java
One of the better Java books out there (Core Java, vol I) has this to say on the matter:
"Dont use protected fields" (8th ed., p 238). The first reason is subclassing, as you explained, and the second is rather Java specific (all classes in package have access).
On the other hand, protected fields (or methods) are useful for the same reason Rachel points out: a kind of marker to indicate something that is not ready for general use and *should* be redifined (read overridden) in a subclass.
Bas Mommenhof wrote
Software dev with one eye on architecture
I tend to disagree with your point. I am writing code using C# and I like to use protected methods for extension.
I use then when I create a class that is intended to be overriden (subclassed) and the protected method is used as an extension point.
Often this method does not contain any code itself but a subclass can add implementation to do some special processing before or after a certain method is executed.
The method can be even defined as "abstract" which means that the no implementation exists in the base class and MUST be overriden.
The fact that a method is protected (to me) indicates that this method has carefully been designed to be overridden.
Through experience I have learned that public methods should never be overridable, because this takes away the garuanteed order in which your code is executed. If you want more information on that let me know and I will take the time to explain. Suffice to say that I have regreted almost every public overridable method I ever made (and converted them to protected).
Also, when you define the class or method as internal (friendly) it means it can only be called or overriden from the same module as the original class is defined.
You can use this to create helper methods that allow your object to get some things done really fast or in a generic way, and not worry about this methods being abused by some external (and thus evil) code written by somebody that not fully understands every minute detail about your class and the way you intended it to be used.
Because face it, these are the truths about programming:
Nobody likes to write documentation, so it's always too little.
Nobody likes to read documentation, so it's always too much.
Even after reading the documentation, the only real way to understand what that documentation meant is create some code and fiddle with it.
The first attempt always fails the first time, so you repeat previous step.
My point is that because something is protected, it does not automatically mean it is public by 'indirection'.
So, protected methods have several usefull functions, mostly to do with the patterns you wish implement within your class.
Greetings.
(ps, if C# and C++ differ greatly on the workings of protected, then this al may make no sense at all, but I believe they arre fairly similar)
Bas Mommenhof wrote
(darn, they beat me to the punch)
rhebus wrote
I agree in principle.
Some methods are open for overriding, but not for calling. Unfortunately, protected isn't quite the right tool for the job. One wants a method that really *can't* be called, but *can* be overridden. But in most languages, protected is the closest you can get. Is there anything in perl 6 which is private-but-overridable?
There's also the case of the protected nonvirtual destructor, useful in C++: http://www.gotw.ca/publications/mill18.htm -- this use case generally doesn't appear in any language with a GC.
George wrote
I'm not going to pontificate on the theoretical benefits and drawbacks of protected members. What I will say, though, is that a massive number of the bugs I've fixed over the years were caused by the use of protected members
Aivar wrote
I would say that protected members are public members with the twist that you can't call them from outside current class.
Tom Dyess wrote
Protected
I use protected member variables when I'm subclassing and I want access to variables I don't want users of the object to have access to.
I'm using the assumption that if you are just instantiating an object, it should encapsulate data as usual, but if you are inheriting that object, you should have full access to anything that object does, and that you know what you are doing. I hate classes that protect me from myself by limiting my use of that class as a parent class.
Dave wrote
I agree, protected attributes make no sense
But you didn't argue that. You argued that protected methods also make no sense. That is just plain wrong. Protected methods are very useful for defining where the original class writer expected their class to be extended. Yes, maybe you want to use their class in a way the author didn't intend for it to be used, but making everything public isn't going to help. It's going to hurt, a lot. And if you REALLY want to do that, just #define protected as public. Just don't expect anyone to handle your bug report.
Inepologlou Lazarus wrote
Software Architect
Public and protected are two different interfaces of the same class that are targeted to different people. The fact that most people will make use of the public interface does not mean that the protected interface is useless: in fact it is very useful for those who work on framework development.
On the other hand, you don't have to invent new uses of the protected interface ("funny yellow hats") if your requirements are nicely covered by the public one!
Markus Mayr wrote
While I agree that protected attributes make no sense, or would only make sense whenever a public attribute would do as well (and these cases are rare). This breaks with the aim to encapsulate a certain part of the program logic into the class most of the time.
However, protected methods are very useful for the above mentioned reasons, i.e. overriding. I consider them as part of the public API. But I think, it can be helpful for the user if he is told "You won't need these methods, unless you want to customize behaviour of this class. What? You really want to? Then please take a yellow hat, read the rules and go on."
This also helps the user to structure his code, as he does not need to encode the desired behaviour into weird and maybe incredible long parameter lists, but he can encapsulate it himself in a (sub) class. You as a developer can use this as well.
In all my code, I could simply replace the protected: line with a public: line and everything would still work and I would still be able to change the internal workings of my classes. It's merely a help for the user of this class in almost all cases.
Therefore, I agree that protected is not essential, but it is definitly nice to have.
Peter Gerdes wrote
Multiple APIs
Basically this comes down to the fact that it can be useful to provide different APIs to different consumers.
To give a simple example imagine I have some kind of data structure that allows search, insertion and delete. For instance perhaps it's a B-tree used to organize filesystem data on disk. Now as a client of this data the only API I should have access to is a generic insert, delete, search API so my code is agnostic as to whether a B-tree or even a linked list is used to store the data. On the other hand if I'm writing filesystem code that tries to efficently and atomicly update this data on disk I may need much deeper access.
Ideally a programming language would support multiple different interfaces to the same object to enable fine grained separation of concerns. Protected attributes are really just a simply way to present two different interfaces, one to extenders who need greater access and another to consumers.
---
Well also protected attributes are useful because C++ doesn't let you intercept setting and getting an attribute so making an attribute protected allows you to keep all accesses of that attribute in a localized part of your code so you don't have to change your whole codebase if you realize that every time obj.x is set to 0 you should really increment obj.count.
Write a comment
The comments on this blog post have been disabled; the comment form below will not work.