SitePoint Sponsor

User Tag List

Page 1 of 3 123 LastLast
Results 1 to 25 of 85

Hybrid View

  1. #1
    SitePoint Addict whydna's Avatar
    Join Date
    Jun 2006
    Posts
    258
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Protected vs Private

    I have read and heard from a few people that say to never use the private access modifier, and instead always use protected. They say this is because you never know who will be extending your class, etc.

    What do you guys think?

  2. #2
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,811
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    Most of the fields that a class uses for its internal processing should not be required to be accessible from any classes derived from that one. The more you can specify as private the easier it will be to maintain the code as there are fewer places where the field can be referenced. You can always shift a field from private to protected later if you need to and the move will have no impact on the code already written.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  3. #3
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I use protected by default. Then again, I tend to minimise use of inheritance, as much as possible, making the choice somewhat obsolete. The problem I have with private, is that it works on the class level. public and protected works on the object instance level. The latter, I can find use for, but the former promotes a way of thinking, which I'm not comfortable with.

  4. #4
    SitePoint Wizard REMIYA's Avatar
    Join Date
    May 2005
    Posts
    1,351
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you want to have something unchanged when your class is used use private, in all the other cases use protected or public.

  5. #5
    SitePoint Addict whydna's Avatar
    Join Date
    Jun 2006
    Posts
    258
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by REMIYA View Post
    If you want to have something unchanged when your class is used use private, in all the other cases use protected or public.
    Yep, I know how the modifiers work.

    The way I see it though is if you declare a method/member private you are essentially saying, "I know every single way that my class will be implemented in the future, and I know for certain that no one will ever need to use this method/member". Of course, we can never know this for sure, as future developers may find a need to call this method, or extend it, right?

  6. #6
    SitePoint Wizard REMIYA's Avatar
    Join Date
    May 2005
    Posts
    1,351
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by whydna View Post
    Yep, I know how the modifiers work.

    The way I see it though is if you declare a method/member private you are essentially saying, "I know every single way that my class will be implemented in the future, and I know for certain that no one will ever need to use this method/member". Of course, we can never know this for sure, as future developers may find a need to call this method, or extend it, right?
    If someone needs a change later he will always make it. The source code is at hand.

  7. #7
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,026
    Mentioned
    64 Post(s)
    Tagged
    0 Thread(s)
    In my own framework all of the classes have the extender _prototype on their names in my core app code. For example

    class PAMWF_Class_prototype {}

    Then if I need to modify the class in a specific project for a client I simply use

    class PAMWF_Class extends PAMWF_Class_prototype{}

    The magic happens in the __autoload function. After it finds a class' file it looks for an override. If it finds it it loads both. Otherwise it wraps the prototype using an eval statement

    eval('class PAMWF_Class extends PAMWF_Class_prototype{}');

    This techinique completly precludes the use of private - I never use it since I don't know when I'll want to customize a block of code for a site.

    It also has the annoying trait of breaking the ability of Zen Studio to follow class relationships, so the code completion features don't work

  8. #8
    SitePoint Zealot Mau's Avatar
    Join Date
    Jan 2006
    Location
    California, USA
    Posts
    134
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by REMIYA View Post
    If someone needs a change later he will always make it. The source code is at hand.
    ...but then maintenance becomes a huge pain. If you are working with an external library, you do not want to go around and change "private" to "protected" every time you upgrade the library. This is one thing that is a minor annoyance about the Zend Framework: everything is either public or private, making inheritance quite useless.

    Another school of thought is that most protected / private methods should be in a different class. Look at your code and I bet most of your private methods should really be in a separate class.

  9. #9
    SitePoint Addict
    Join Date
    Oct 2006
    Posts
    210
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by whydna View Post
    The way I see it though is if you declare a method/member private you are essentially saying, "I know every single way that my class will be implemented in the future, and I know for certain that no one will ever need to use this method/member". Of course, we can never know this for sure, as future developers may find a need to call this method, or extend it, right?
    Providing public or protected access to member variables / methods implies that those elements will not change in form or function. Because changing them will likely impact the client code that accesses them. For closed projects where have access to both the class and the client code, changing an accessible variable / method might not seem like a big deal but it depends on how much code needs to be changed. For cases where I'm providing a library to others outside my team, I need to be careful about changing public and protected member variables / methods.

    Just my $0.02 worth....
    mikem

  10. #10
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by whydna View Post
    The way I see it though is if you declare a method/member private you are essentially saying, "I know every single way that my class will be implemented in the future, and I know for certain that no one will ever need to use this method/member". Of course, we can never know this for sure, as future developers may find a need to call this method, or extend it, right?
    I strongly agree. You should always be able to extend a class in any way you see fit. Final and private are a complete no-no in my book. If you feel the need to protect bits within a class that's probably a smell indicating that something ought to be split off into a separate class.

    I'd go even further though: don't use any of them and instead stick with the underscores we used in php4. Clearly labelling the public interface is important. Enforcing it is not. All they do is add clutter.

  11. #11
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,811
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    There is nothing to stop you updating the class in the future to move something from private to protected if it turns out you need it that way. Just a minor change to an existing class that would have no impact whatsoever on anything currently using it.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  12. #12
    SitePoint Guru
    Join Date
    Nov 2003
    Location
    Huntsville AL
    Posts
    689
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by felgall View Post
    There is nothing to stop you updating the class in the future to move something from private to protected if it turns out you need it that way. Just a minor change to an existing class that would have no impact whatsoever on anything currently using it.
    Not necessarily. If a derived class tries to access a private variable then __get() will get kicked off. The __get() implementation might then return some particular value. If the ancestor variable is then changed from private to protected then __get will no longer be called.
    PHP Code:
    class Base
    {
        private 
    $shy 27;
    }
    class 
    Extend extends Base
    {
        function 
    __get($name) {
            if (
    $name == 'shy') return 42;
        }
        function 
    run()
        {
            echo 
    "Shy {$this->shy}\n";
        }


  13. #13
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    232
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by felgall View Post
    eval('class PAMWF_Class extends PAMWF_Class_prototype{}');
    That sounds like a great idea, then you need to change your name to Michael Morris, right? :P

  14. #14
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    232
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by felgall View Post
    There is nothing to stop you updating the class in the future to move something from private to protected if it turns out you need it that way. Just a minor change to an existing class that would have no impact whatsoever on anything currently using it.
    If a company has 20 programmers, only 4 of them have write access to core classes, and you are not one of them, how are they going to extend it?

    Usually, in big companies, you can only checkout core components. If one of the core developers assumed that no one will ever need to extend that class, he is either psychic or human (we all make mistakes).

  15. #15
    SitePoint Enthusiast
    Join Date
    Mar 2005
    Posts
    47
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by phpimpact View Post
    If a company has 20 programmers, only 4 of them have write access to core classes, and you are not one of them, how are they going to extend it?

    Usually, in big companies, you can only checkout core components. If one of the core developers assumed that no one will ever need to extend that class, he is either psychic or human (we all make mistakes).
    Yep, which is similar to a situation I am encountering at work. There is a class that I want to basically add some functionality and members to, so that it is basically a "smarter" class.

    However, most of the stuff is declared as Private (I guess the original programmer felt there would never be a need to upgrade it) and I do not have write access to the base class. What can I do? Since I cannot inherit from it and add extra functionality, I am forced to basically duplicate the class and all its members/methods or use aggregation.

  16. #16
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    [RANT]

    Experience taught me that access modifiers, as currently defined in Java and therefore PHP, are the worst possible solution because they mix classes and objects, as kyber noticed earlier.

    Private, in particular, is a crazy idea, because in practice the object instances are those that interact with other objects, not the classes. The problem is someone didn't realize that access control and inheritance rights are two separate problems and has tried to solve them with a single solution.

    In a perfect world, we would have only one access modifier, and that is public; everything else would be by default private (or even better "internal"), meaning that only the instance itself can access its internal members. And neither would affect inheritance in any way.


    [/RANT]

  17. #17
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I never use private, but I do use protected quite a bit. I don't want to prevent someone down the road from modifying my classes or adding functionality by extending them - I sometimes don't even think final and private should exist in the language, because they eliminate most of the benefits object-oriented programming provides.

  18. #18
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by BerislavLopac View Post
    In a perfect world, we would have only one access modifier, and that is public; everything else would be by default private (or even better "internal"), meaning that only the instance itself can access its internal members.
    The sensible default is to make methods public, and data members protected. At the very least, we need those access modifiers.


    Quote Originally Posted by Czaries View Post
    I sometimes don't even think final and private should exist in the language, because they eliminate most of the benefits object-oriented programming provides.
    Interestingly, in Ruby private is like PHP's protected; Ruby's protected is the same, but allows other objects of the same type to see the method/member. In all cases, subclasses can see the method or member. Somewhat unorthodox, but more useful IMO.

  19. #19
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by 33degrees View Post
    Interestingly, in Ruby private is like PHP's protected; Ruby's protected is the same, but allows other objects of the same type to see the method/member. In all cases, subclasses can see the method or member. Somewhat unorthodox, but more useful IMO.
    That sounds a bit odd too, although slightly better than the PHP way. I'm some times missing a friend access modifier. This would allow you to expose members, but only to a certain number of classes. That would be quite useful, if you use a lot of aggregation.
    Ruby does another thing though, which is very nifty; It makes all properties protected, and only allows you to expose methods. This is something, which is clever to enforce at the language level. In contrast, PHP makes all properties public by default.

  20. #20
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    That sounds a bit odd too, although slightly better than the PHP way.
    Ruby has a few idiosyncrasies like that; having 0 evaluate to true (rather than false) is another. But having private available to subclasses makes more sense anyway.

    Quote Originally Posted by kyberfabrikken View Post
    I'm some times missing a friend access modifier. This would allow you to expose members, but only to a certain number of classes. That would be quite useful, if you use a lot of aggregation.
    I don't know, I've always thought that over reliance on "friend" can lead to hard to maintain code.


    Quote Originally Posted by kyberfabrikken View Post
    Ruby does another thing though, which is very nifty; It makes all properties protected, and only allows you to expose methods. This is something, which is clever to enforce at the language level. In contrast, PHP makes all properties public by default.
    Ruby also makes it trivial to add getters and setters, so there's no reason to make properties public anyway.

  21. #21
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by 33degrees View Post
    I don't know, I've always thought that over reliance on "friend" can lead to hard to maintain code.
    If the alternative was public, I think it would be preferable. I'm not sure though. Right now, I just end up with a lot of public functions and a lot of protected attributes, and frankly it doesn't bother me too much. The friend accessor has another problem associated with it, in that it would tend to create concrete class dependencies (Unless a friend could be an interface).
    All very theoretical -- I'm not at all suggesting, that this should be introduced into PHP at this point. That would just serve to further muddle things.

  22. #22
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Posts
    27
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Actually I think you miss the point Athox, this discussion is not about how to initialize a variable properly, its not even a discussion about setters/getters but a discussion about access modifiers, and in terms of OOP (namely inheritance) private (as PHP implements it) is bad practise.

    I agree on the other hand that you should set default values in the constructor, not within the declaration, because as long as the constructor isnt called we have a class without any state, and as such it shouldnt have any values. When the constructor is called however, the class turns into an instance, and as such it can have (default) values

  23. #23
    SitePoint Enthusiast
    Join Date
    Oct 2006
    Posts
    85
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by myc View Post
    Actually I think you miss the point Athox, this discussion is not about how to initialize a variable properly, its not even a discussion about setters/getters but a discussion about access modifiers, and in terms of OOP (namely inheritance) private (as PHP implements it) is bad practise.
    Yeah, but PHP implements that part exactly the same way as most other languages.

    Either way, my argument earlier was that attributes should be as private as possible. And someone started giving me a lecture about how to match OOP with real world objects, and somewhere near that part someone else were talking about how methods should be the external communication for the object.
    Can't the two posters just read each others posts and save the world? It would be great.

    Having private attributes is one thing. If you want it to be changed in the subclasses, but still not from outside the class, just make the getter and setter protected. It's the correct way, no matter how you put it.

    People's personal interpretations of how OOP should work are not very objective, are they? (pun intended )

  24. #24
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Athox View Post
    Yeah, but PHP implements that part exactly the same way as most other languages.
    Which doesn't mean that the other languages got it right.

    Quote Originally Posted by Athox View Post
    Either way, my argument earlier was that attributes should be as private as possible.
    This isn't an argument, it's an opinion, and it heavily depends on how you define the term "private". In "most other languages" (as you put it) this keyword restricts two completely separate things: which objects may access a property, and which properties are inherited by a subclass. My point was that these are two completely separate concerns and should not be controlled by a single language construct.

    Check out how is access defined in Smalltalk; here's an excerpt from the Wikipedia article:
    The state an object holds is always private to that object. Other objects can query or change that state only by sending requests (messages) to the object to do so. Any message can be sent to any object: when a message is received, the receiver determines whether that message is appropriate.
    In other words, you might or might not be right -- depending on the definition of the word "private", which depends on the language used. Considering we are on a PHP board, if we consider PHP you are actually wrong, as "private" inflicts inheritance restrictions which are actually harmful.

    Quote Originally Posted by Athox View Post
    And someone started giving me a lecture about how to match OOP with real world objects, and somewhere near that part someone else were talking about how methods should be the external communication for the object.
    I think both of these points were mine, and as I replied above my intention wasn't to lecture anyone, and especially not you. Naturally not all methods will be public; there is a ton of uses for purely internal methods. However, an object is defined by its external behavior, which is implemented by public methods. This is the same thinking which stands behind interfaces -- an interface is actually a "type", as it defines the method signatures required for an object to be of that type.

    Quote Originally Posted by Athox View Post
    Having private attributes is one thing. If you want it to be changed in the subclasses, but still not from outside the class, just make the getter and setter protected. It's the correct way, no matter how you put it.
    Your error here lies in the words "If you want it to be changed in the subclasses, but still not from outside the class" -- no attributes are changed inside or outside of a class. You don't run your methods on a class -- you always call them upon an instance of a class. The only exception are static members, but in PHP they don't differ from global variables/functions except in regards to organization of code.

  25. #25
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by myc View Post
    I agree on the other hand that you should set default values in the constructor, not within the declaration, because as long as the constructor isnt called we have a class without any state, and as such it shouldnt have any values. When the constructor is called however, the class turns into an instance, and as such it can have (default) values
    Actually, that's not strictly true, at least not in all cases. I've noticed that, when using PDOStatement->fetchObject(), the resulting object will have it's properties set BEFORE the constructor is called. While this is most likely a bug, it does show that objects do have state before the constructor is called.

    In any case, there are situations where it is preferable to give properties default values, as these values can be queried using get_class_vars().


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •