SitePoint Sponsor

User Tag List

Page 1 of 4 1234 LastLast
Results 1 to 25 of 85
  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,803
    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
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,803
    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="^$">

  7. #7
    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";
        }


  8. #8
    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.

  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
    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

  11. #11
    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

  12. #12
    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).

  13. #13
    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.

  14. #14
    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.

  15. #15
    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.

  16. #16
    SitePoint Wizard REMIYA's Avatar
    Join Date
    May 2005
    Posts
    1,351
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Mau View Post
    ...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.
    If you work with an external library and you meet private, you will have to go in the core of that library and make your changes. It would be good, if you supply your changes to the initial developer, too.

    Quote Originally Posted by Mau View Post
    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.
    This is a very wrong approach, if I need something private, that means I want it private. Otherwise, I would separate it in a different class.

  17. #17
    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]

  18. #18
    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.

  19. #19
    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.

  20. #20
    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
    This is a very wrong approach, if I need something private, that means I want it private. Otherwise, I would separate it in a different class.
    I somewhat disagree. I often see code like this:
    PHP Code:
    class RaceCar
    {
      ...

      protected function 
    writeToLog($msg)
      {
        
    file_put_contents('foo'$msg);
      } 

    writeToLog() is not part of the racecar and does nothing related to racing. Shouldn't that be abstracted out to a different class?

    PHP Code:
    class Logger 
    {
    }
    class 
    Racecar
    {
      protected 
    $logger;
      public function 
    __construct(Logger $logger)
      {
        
    $this->logger $logger;
      }
    }

    $logger = new Logger;
    $racecar = new Racecar($logger); 
    In my opinion, that is much cleaner code, even though it's twice as long. It also correctly delegates tasks and classifies functions.

  21. #21
    SitePoint Wizard REMIYA's Avatar
    Join Date
    May 2005
    Posts
    1,351
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Mau View Post
    In my opinion, that is much cleaner code, even though it's twice as long. It also correctly delegates tasks and classifies functions.
    What does it have with private and protected?

  22. #22
    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
    What does it have with private and protected?
    I fear we are getting off topic, but all I was doing was making a comment on how most protected methods could actually be public methods in a different class. In the above post, I was providing an example of when a protected method should actually be public.

  23. #23
    SitePoint Wizard REMIYA's Avatar
    Join Date
    May 2005
    Posts
    1,351
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Mau View Post
    I fear we are getting off topic, but all I was doing was making a comment on how most protected methods could actually be public methods in a different class. In the above post, I was providing an example of when a protected method should actually be public.
    Actually the first class you have put as an example is a bad implementation no matter of the private, protected or public methods used.
    The second one is just a step better, but the whole example is far from the topic being discussed.

  24. #24
    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.

  25. #25
    SitePoint Enthusiast
    Join Date
    Oct 2006
    Posts
    85
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Dudes, learn OOP. Keyword: encapsulation. Attributes should be as private as possible and methods should be as public as possible.

    You should use getters and setters, and these should be final and public (if applicable). If they require some sort of validation, then that validation should be within a separate protected method in case it is edited later, while the setter is still final.

    There are rules for OOP, which are often overlooked. It's quite simple, and logical. Even more complex classes should follow this simple pattern. Of course, if your original class is bad to begin with, then there's of course nothing you can do, and you shouldn't even bother. Do it again.

    PHP Code:
    // initial class
    class MyClass {
      private 
    $name;

      public function 
    __construct($name) {
        
    $this->setName($name);
      }

      final public function 
    getName() {
        return 
    $this->name;
      }

      final public function 
    setName($name) {
        if (
    $this->isValidName($name)) {
          
    $this->name $name;
        } else {
          echo 
    "Name was bad.\n";
        }
      }

      protected function 
    isValidName($name) {
        return 
    preg_match('/^[a-z]+$/i'$name);
      }
    }

    // improved class
    // we need to change isValidName() to be more restrictive about uppercase letters.
    class MyImprovedClass extends MyClass {
      protected function 
    isValidName($name) {
        return 
    preg_match('/^[A-Z][a-z]+$/'$name);
      }
    }

    $class = new MyClass("ALICE");
    echo 
    $class->getName() . "\n";
    $class = new MyImprovedClass("ALICE");
    echo 
    $class->getName() . "\n";
    $class = new MyImprovedClass("Alice");
    echo 
    $class->getName() . "\n";

    // Outputs:
    ALICE              // MyClass::getName()
    Name was bad.  // MyImprovedClass::setName()
                          // MyImprovedClass::getName()
    Alice               // MyImprovedClass::getName() 


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
  •