SitePoint Sponsor |
|
User Tag List
Results 51 to 75 of 85
Thread: Protected vs Private
-
Jan 21, 2008, 06:39 #51
- Join Date
- Sep 2006
- Posts
- 232
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
REMIYA, what you are saying is different from what Athox is saying. You are talking about flexibility, about attributes being private or protected. On the other hand, Athox is suggesting that there should be NO flexibility and that all the attributes should be private.
Athox is wrong, the following example will not work because of the private attributes:
PHP Code:class ClassA {
private $_fooA = 'ClassA::_fooA';
private $_fooB = 'ClassA::_fooB';
protected function _setFooA($value) {
$this->_fooA = $value;
}
protected function _setFooB($value) {
$this->_fooB = $value;
}
public function getFooB() {
return $this->_fooB;
}
}
class ClassB extends ClassA {
}
class ClassC extends ClassB {
private $_fooB = 'ClassC::_fooB';
}
$obj = new ClassC();
print $obj->getFooB();
Code:ClassA::_fooB
-
Jan 21, 2008, 19:37 #52
Good thing that constant is documented in the manual... oh what, it's not. In fact, the only thing of use googling turns up is a couple of posts you made on this site a while back.
In any case, if it's not a bug, it's certainly NOT intuitive behavior, and it just proves my point; that in PHP, it's possible for an object to have state before the constructor is called.
-
Jan 24, 2008, 05:18 #53
- Join Date
- Nov 2006
- Posts
- 6
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I think that there two good reasons to keep most attributes private. Private attributes assist versioning and refactoring. Refactoring include renaming the private attributes to reflect better understanding of the code. Refactoring also allows the type and/or data structure of the attribute to change for the purpose of optimisation or further simplification of the code. If the said attributes were protected or public, more code needs to be examined to perform the same task of refactoring. Even worse, not probably infeasible, if those code is directly out of reach for refactoring, e.g. used by 3rd parties.
Versioning closely follows refactoring as the design of the class evolves. This may include providing accessors and mutators to the private attributes as need arise. The user of the class should only need to understand the public API. In particular, a public method/attribute should be an unbreakable contract for the class if there is need to keep backwards compatibility (this is one aspect of versioning). This requires that each public method/attribute be carefully named and designed. Promoting a private attribute and/or method to protected or public must require careful consideration. The less protected/public attributes/methods are available, the easier it may be to permit versioning of the code.
These features, versioning and refactoring, become very important as the code base become large and age.
-
Jan 24, 2008, 06:58 #54
- Join Date
- Sep 2003
- Location
- Glasgow
- Posts
- 1,690
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Honestly, both private and protected just make life unnecessarily complicated. You don't need either of them. What unit test would fail if you made something which was private/protected public?
We have to ruthlessly strip away unnecessary clutter. The task of programming is to make things as simple and as clear as we possibly can.working on: Aperiplus, Rephactor, Phemto
useful links: xUnit test patterns, martinfowler.com, c2 wiki
-
Jan 24, 2008, 08:50 #55
- Join Date
- May 2007
- Location
- The Netherlands
- Posts
- 282
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Design patterns: trying to do Smalltalk in Java.
I blog too, you know.
-
Jan 24, 2008, 09:44 #56
- Join Date
- Sep 2003
- Location
- Glasgow
- Posts
- 1,690
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
It is of course important that there should be a clearly defined interface and that this should be clearly labelled but it doesn't need to be enforced. The risk that people might wrongly call the wrong (notionally private) methods is hugely over-exaggerated IMO. It's so incredibly unlikely that you might as well say that it doesn't exist.
working on: Aperiplus, Rephactor, Phemto
useful links: xUnit test patterns, martinfowler.com, c2 wiki
-
Jan 24, 2008, 15:32 #57
- Join Date
- Jun 2003
- Location
- Melbourne, Australia
- Posts
- 440
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I rather like public and protected (don't see the need for private), at least for class variables. I can see that the need for those declarations in methods is less. To an extent, though, I'm with McGruff when he says...
it doesn't need to be enforcedLast edited by auricle; Jan 26, 2008 at 03:29. Reason: clarity
Zealotry is contingent upon 100 posts and addiction 200?
-
Jan 25, 2008, 11:16 #58
I agree with you, if we're talking about methods. However, we're also talking about attributes, and there's a real danger to having those be public, as it violates encapsulation. The need to maintain encapsulation comes above all else, as it will bite you in the *** somewhere down the line.
-
Jan 29, 2008, 11:28 #59
- Join Date
- Oct 2006
- Posts
- 85
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
First of all, I didn't say that all attributes should be private. I said they should be as private as possible, which means that if you can avoid them being protected, you should.
Athox is wrong, the following example will not work because of the private attributes:
PHP Code:class ClassA {
private $_fooA = 'ClassA::_fooA';
private $_fooB = 'ClassA::_fooB';
protected function _setFooA($value) {
$this->_fooA = $value;
}
protected function _setFooB($value) {
$this->_fooB = $value;
}
public function getFooB() {
return $this->_fooB;
}
}
class ClassB extends ClassA {
}
class ClassC extends ClassB {
private $_fooB = 'ClassC::_fooB';
}
$obj = new ClassC();
print $obj->getFooB();
PHP Code:class ClassA {
private $_fooA;
private $_fooB;
public function __construct() { // constructor to set default values!!
$this->_setFooA('ClassA::_fooA');
$this->_setFooB('ClassA::_fooB');
}
// ... snip ...
}
class ClassB extends ClassA {
}
class ClassC extends ClassB {
public function __construct() { // constructor!!!!!!!!!!
parent::__construct(); // call parent constructor unless you know you're overriding it 100%
$this->_setFooB('ClassC::_fooB');
}
}
$obj = new ClassC();
print $obj->getFooB();
-
Jan 29, 2008, 11:44 #60
- Join Date
- Oct 2006
- Posts
- 37
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I agree that they should be as private as possible.
No one is making you do this, it's up to you. But it's for your own improvement if you follow that guideline. Because it provides a more stable coding model down the road.
Making all attributes public is just silly. For a quick and dirty it will work, but anything decent should properly use getters and setters. And if you find yourself writing too many of them, then you probably need to rethink your design.
I agree with you, if we're talking about methods.
Don't think you wouldn't use that method, because when you are in a time pinch you will use whatever works quickest.
-
Jan 29, 2008, 11:54 #61
- Join Date
- Oct 2006
- Posts
- 85
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
You will never break any use of a method by making it MORE public.
-
Jan 29, 2008, 19:00 #62
- Join Date
- Sep 2006
- Posts
- 232
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Athox, you are not getting the point. In php you can do it both ways. Saying that you shouldn't set values to attributes directly doesn't make sense. What you are saying is: "I'm right, everyone is wrong". And by saying that, you are suggesting that all the php frameworks should be rewritten.
Maybe that's how you do it, and it's fine. But please, don't bring strictness to a language that's completely the opposite.
-
Jan 29, 2008, 21:25 #63
- Join Date
- Aug 2007
- Posts
- 365
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I dont have a klot of time for an explination right now, but Ill be quick.
If you are usign Getters and Setters you should set your varible to be private.
If not and dont need access to the outside world use public ( depending on type),
else use private..
Ill explain later if anyone is interested
-
Jan 29, 2008, 21:53 #64
- Join Date
- May 2007
- Location
- The Netherlands
- Posts
- 282
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
In my personal experience, protected methods often end up somewhere in helper classes or functions because they provide methods that don't really fit the concern the class is trying to cover. I also hardly have any protected variables because I simply avoid using inheritance.
The only 'real' problem I have with the protected keyword is that you're limiting the data to subclasses and are thus forcing someone that needs the data to inherit, so the data I end up marking as protected ends up public anyway because I don't want to force anyone to inherit. Private doesn't have this problem, because most of the time the data marked as such is irrelevant elsewhere.
There is nothing wrong with the protected keyword, however, because it certainly has it's uses. However, what I described above is the way my codebases usually seem to evolve.Design patterns: trying to do Smalltalk in Java.
I blog too, you know.
-
Jan 30, 2008, 01:33 #65
- Join Date
- Mar 2006
- Location
- Sweden
- Posts
- 451
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Jasper:
So do you set your class properties to public, och do you have public getters for them and set the properties to private/protected?
-
Jan 30, 2008, 04:54 #66
- Join Date
- Sep 2006
- Posts
- 232
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I simply avoid using inheritance
I use private in rare circumstances, I always use setter to assign values, and if I need to, I also assign default values to attributes, depending on the design of the class.
I think it's not about using one or the other, is about using the one that fits best to a given design. I'm against forcing the user to adapt to my class, I prefer a flexible design where the class adapts to the user. Because the truth is that we don't know how he's going to use it.
IMO, a good design should be flexible enough to adapt to different needs. Someone that designs a class should not base the design on personal preferences. E.g.: never set values in attributes, don't use inheritance, etc.
Private reduces the options, while protected opens up the possibilities.
-
Jan 30, 2008, 05:57 #67
- Join Date
- Mar 2006
- Location
- Sweden
- Posts
- 451
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Just a thought; making a varible public can screw things up, but it's also kind of annoying to write getters for every variable. How about having another definition, a readonly sort of thing? That means you can read a class variable, without having to create a getter, but it reduces the risk of another object screwing up the object. This could also be done by setting the variable to private/protected, and using __get() to return the variable, so that:
echo $obj->var; works, but $obj->var = 'asd'; won't work.
-
Jan 30, 2008, 08:22 #68
- Join Date
- Sep 2003
- Location
- Glasgow
- Posts
- 1,690
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Up to a point. We do have to think how to make code simple to use and extend but I think it's OK to assume a basic level of competence. I haven't ever seen anyone mistakenly try to call a notionally private method in php4 before we had all this access stuff. We do need to clearly label the public interface but I don't think we need to enforce it.
I'm very much a test-infected programmer. Write a test; write the simplest code to pass the test; now move on. Test-first means that you don't write anything except in response to a real requirement (expressed by the test). The "simplest thing" mantra is very important. Code is harder to refactor once you start accumulating unnecessary complexity. It's harder just to read it before you even get started analysing how well you've cut the OOP cake.
You have to be ruthless: if there's anything which can be cut out without affecting functionality (ie all the tests still pass) it must be cut out. If you don't do that you'll gradually gather up all kinds of baggage. Complexity tends to breed yet more complexity and our task is to cut through that, writing the simplest, clearest code we can think of.
Unless I have a failing test (a desired behaviour which hasn't yet been implemented) which can only be made to pass by adding an access modifier, I won't add them - and I cannot think of any real requirement for access restrictions which can be expressed in the language of the domain. The last bit is important: you could of course write a test: "testNobodyCanCallMyPrivateMethod" but this sounds like it's testing implementation not behaviour.
I joined a new project recently which has a full suite of tests. Guess what happens when you remove all the access stuff? Absolutely nothingAll the tests still pass.
working on: Aperiplus, Rephactor, Phemto
useful links: xUnit test patterns, martinfowler.com, c2 wiki
-
Jan 30, 2008, 08:38 #69
- Join Date
- May 2007
- Location
- The Netherlands
- Posts
- 282
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I use them whenever I need them; however I feel that they are bad design because they are not defining behavior. But sometimes they're needed because you have some sort of dirty flag to set or other actions that need to be performed whenever a variable changes. Another reason is that the data exposed in this way, can be defined in an interface and the classes that use the interface are now decoupled from the implementation.
Not using inheritance is not so much a preference as it is a necessity for good design in my opinion. In the optimal case, all polymorphism happens though an interface because it reduces coupling. There are cases where that option seems wrong because it introduces code duplication, however you can always refactor the duplicate code into a separate class.
One example of this, is that I had modeled my controllers as a interception filter, each class had a next() method that stored a reference to the next controller in the list and that every execute() method had to determine if there was another controller on the chain and call it if it existed.
This is duplicate code and you really don't want that (that and because has O(n) performance, which might some day become a problem). Solving this involved refactoring all (!) the controllers and separating the traversal algorithm, which one might say, is a different concern anyway. The next big refactoring will be to change the way I determine which controller handles the request; currently every controller has a can_i_handle_this($request) type of method, that really shouldn't be there. But that something I have to think about some more before I will actually implement it.
Private reduces the options, while protected opens up the possibilities.
I recently did a grep for 'extends' over one of my code bases, one that I think has a great design and I only encountered it when a third party product required me to use it, or when I extend an interface such as below.
PHP Code:interface NamedObject{
function get_name();
}
interface NamableObject extends NamedObject{
function set_name();
}
Design patterns: trying to do Smalltalk in Java.
I blog too, you know.
-
Jan 30, 2008, 08:48 #70
- Join Date
- May 2007
- Location
- The Netherlands
- Posts
- 282
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
That's because they're testing behavior and not implementation (which they should); it doesn't make sense to test the state of every public variable because variables are not interesting (really, they're not). My solution to this is to make them private since nobody cares about them anyway, while yours it to keep them public because it would add clutter. The nice thing about this is that it doesn't really matter which solution you chose if the design is good, because when you're programming against behavior (interfaces in my case, unit tests in yours), there is no way on earth that you are going to want to touch variables explicitly.
Design patterns: trying to do Smalltalk in Java.
I blog too, you know.
-
Jan 30, 2008, 11:07 #71
- Join Date
- Sep 2006
- Posts
- 232
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Jasper, I'm starting to like your philosophy and you are right, but because you are an experienced programmer, and you know what you are doing and why you are doing it. But imagine someone with less experience than you that reads "not using inheritance is a necessity for good design". I'm sure that they are going to close the browser, open up an editor and create the biggest God object that we've ever seen. And God objects are my worst nightmare.
Experienced programmers not using inheritance, yes, I trust them.
-
Jan 30, 2008, 11:57 #72
That's a flaw with PHP, just as it is with Java.
That's a very type-centric way of viewing things. In my view, there are no interfaces, polymorphism happens through objects implementing the right methods, and inheritance is used to specialize behavior.
-
Jan 30, 2008, 12:03 #73
-
Jan 30, 2008, 12:16 #74
- Join Date
- Oct 2006
- Posts
- 37
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
-
Jan 30, 2008, 14:00 #75
- Join Date
- Oct 2006
- Posts
- 85
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
You're not supposed to get the value for an attribute. You're supposed to get a certain state of an object. That's the point of OOP. If you wanted the value of an attribute then you should use global variables, which isn't necessarily bad, but it's bad in an OOP context. The attribute can change name or purpose at any time, but the interface remains the same, namely a getter.
Say you have a Shape, and you have a getter called getShape(), which returns the shape in question. Now, there is an attribute in there called $shape, which holds the number of sides to the shape.
Originally, the getter returned a shape with symmetrically placed corners. (think of an image)
Later we changed it to return a shape with the correct number of sides, but with randomly positioned points/corners. But if you'd called the attribute directly, you would have still received the symmetrical shape.
It's an abstract example (for your head), which can't be implemented in programming terms, but it was the first thing I thought of.
Also, the setters are more important to implement, because they may (and possibly should) contain integrity checks: Is the value a number or an array or is the string in the correct format, etc.
Bookmarks