开发者

Reasoning Behind PHP5 Protected Variables

Can you explain what the reasoning would be on why I would want to use "protected" versus "public" or "private" on some class variables and met开发者_C百科hods in PHP5? I've just yet to find a case where I thought I needed "protected", and have either opted for "public" or "private" based on the intent. Even when working in teams, I have still yet to find a case (based on my knowledge thus far) of why "protected" is necessary for class variables and methods.


For instance, the Flourish library's fDate class provides a lot of functionality but not everything I need. So I extended w/ my own class.

I soon found out that its core internal variable, fDate::$date (time in seconds since 1970), was a private property. This made it impossible for me to access it in my subclass ThriveDate. Once the maintainer of Flourish changed it to a protected property, I was able to use it and thus adequately extend fDate.

Since you never know who might need to extend your class, and by how much, in the future, it's always best to make every internal property protected, unless there are great reasons for the property to never be modified by subclasses.

TL;DR: Private properties should be as rare as public properties: e.g. used almost never.


With protected its possible for an object of the class or any subclass to access that property. So its useful, if you want this restriction.

This is not strictly necessary, you can also make every property public, but then you will lose every control, who access and/or changes it. Also others may get confused, what all these "public properties" are good for, for which they have access to.

On the other hand you can make every property private, but then also every subclass can not access it anymore.


What about a real life example:

<?
// burguers.php

/* abstract */ class BurguerClass {
  // nobody knows about these secret function
  private function addSecretRecipeSauce() { ... }  

  // these one can can change in subclasses
  // cannot be called globally
  protected /* virtual */ function addBread() { ... }  
  protected /* virtual */ function addSalad() { ... }  
  protected /* virtual */ function addMeat() { ... }
  protected /* virtual */ function addExtraIngredients() { ... }

  // these one it can be access globally
  public /* virtual */ function makeBurguer() {
    $this->addBread();
    $this->addSalad();
    $this->addMeat();
    $this->addExtraIngredients();
    $this->addSecretRecipeSauce();
  }  
}

/* concrete */ class CheeseBurguerClass extends BurguerClass {
  protected /* virtual */ function addCheese() { ... }

  public /* override */ function makeBurguer() {
    $this->addBread();
    $this->addSalad();
    $this->addMeat();
    $this->addExtraIngredients();
    // we add this one:
    $this->addCheese();
  } 
}

/* concrete */ class RanchStyleBurguerClass extends BurguerClass {
  protected /* override */ function addExtraIngredients() { ... }
}

/* concrete */ class EastCoastVegetarianStyleBurguerClass extends BurguerClass {
  protected /* override */ function addMeat() {
    // use soy "meat"
  }
  protected /* override */ function addExtraIngredients() { ... }
}

function burguers_main() {
    $Cheesburguer = new CheeseBurguerClass();

    // can be access
    $Cheesburguer->makeBurguer();
}

// execute it
burguers_main();

?>

You just open the "Can I have a Cheesburguer" Software Development company. You are the C.E.O., you have several subordinates. You teach subordinates they can make new products based on the "burguerClass" recipe, and make new recipes.

You tell your employees how to "addBread" , "addSalad", "addMeat", "addExtraIngredients", and that operations can be changed by new ones, but cannot sell them separately, only can used in the "makeBurguer" operation.

But, you dont teach your employees the "addSecretRecipe" operation.


The way I understand it is that Private methods and properties cannot be seen by classes that extend; whereas Protected methods and properties can be seen but used only by the class it is defined within.

http://php.net/manual/en/language.oop5.visibility.php


when designing classes, isn't it normal to have private and public variables or properties.

Granted my OOP experience is very limited, having access to OOP development in CA-Visual Objects, Clipper, VB, and ASP.

But it was normal to have a series of public properties one could access directly and then properties that could only be access by the class itself.

Of course in VB and ASP these were defined with Get, Let and Set methods, but you could still access them directly.

You could also design properties that were read only as well. Perhaps this is because of operator overloading...


I use protected methods and attributes rather than private mainly for testing purposes. This way it's much easier to create class mocks when writing unit tests.


OOP doesn't ends at organizing your code to classes (as structured programming doesn't ends at splitting code to functions). PHP is a script language, so when using it as OOP language, we should set up contstraints for ourselves.

I was very lucky, when I first met OOP, the language was Java, and the book was Bruce Ekcel - Thinking in Java (you can purchase it on Amazon or other stores, also previous editions can be downloaded from here for free: http://www.mindviewinc.com/Books/downloads.html ). I can recommend that book, even for PHP programmers. If you're not complete beginner, you will understand everything, and adopt it to PHP. I'm trying to programming in PHP like if it were Java (at least, the OOP part; there're no such cool associative arrays in Java, as in PHP).

Also, private, protected, and public categories are not too precise. Public should be split to "API method" and "can be called from other classes" (see "friendly"), protected should distinguish between "should be overwritten" and "must be implemented".

Learn OOP, it's worth.

There's one more thing I wanna to say, a basic pattern of OOP: use getters/setters, don't use public properties, if you use public properties, you just graved it to rock. Say, there's a status flag, now it has 2 possible state values, but if you wanna extend it, all the code must be revised, which use it. Use setState() and getState(), which functions first are simple ($this->state = $param; and return $this->state), but there will be no problem with extending the meaning of state, then you should re-write only these methods, even in the case, if the state is a derived value (e.g. its value is calculated from more flags).

There're several less or more deep similar topics in OOP, this getter/setter is probably the most important of the basic ones.

So, my tips are:

  • use OOP, it's your friend;
  • use PHP as like it were JAVA (a strict OOP language), and not like in FORTRAN.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜