0

Hello I was wondering why some popular PHP libraries make all properties protected, then add get and set methods for them like:

  protected
    $a = false;

  public function getA(){
    return $this->a;
  }

  public function setA($value){
    $this->a = (bool)$value;
  }

What's the benefit of this and why not simply make the property public?

Yang
  • 8,580
  • 8
  • 33
  • 58
katie
  • 991
  • 2
  • 11
  • 19
  • 1
    possible duplicate of [Why use getters and setters?](https://stackoverflow.com/questions/1568091/why-use-getters-and-setters) – Boann Oct 05 '14 at 16:39
  • Here's a great answer to: [Why use getters and setters?][1] [1]: http://stackoverflow.com/a/1568230/3916476 – tenhsor Oct 05 '14 at 16:42

3 Answers3

4

OOP real world scenario:

Imagine you have a class Vehicles and they have (protected) wheels. You have different Vehicles with wheels, but to addWheel to a Bike, is different from addWheel to an Aircraft.

Code advantage:

Using getter and setter, you can use typehinting.

Compare those snippets:

class Car {
    public $wheels;
}

$bmw = new Car;
$bmw->wheels = 'piece of paper';

The above code let's you add anything as a wheel, but can you use a piece of paper as a wheel?

Now with getter and setter:

class Car {
    protected wheels;
    public function __construct() {
        $this->wheels = new ArrayIterator;
    }

    public function addWheel(Wheel $wheel) {
        $this->wheels->add($wheel);
        return $this;
    }
    public function removeWheel(Wheel $wheel) {
        $this->wheels->remove($wheel);
        return $this;
    }
 }

 class Wheel {
 }

 $bmw = new Car;
 $bmw->addWheel('piece of paper'); // <-- throws an error!
                                   // paper cannot be used as a wheel

 $bmw->addWheel(new Wheel); // <-- good :-)

More code, to be more straightforward. Imagine you have RearWheels and FrontWheels:

class Wheel {
}

class FrontWheel extends Wheel {
}

class RearWheel extends Wheel {
}

class Car {
    protected wheels;
    public function __construct() {
        $this->wheels = new ArrayIterator;
    }

    public function addWheel(Wheel $wheel) {
        // check for already existing Wheels here.
        // Pseudo Code:
        if (wheels typeof RearWheel > 2) {
            throw new Exception('cannot add more than 2 RearWheels to the Car');
        }
        return $this;
    }
    public function removeWheel(Wheel $wheel) {
        $this->wheels->remove($wheel);
        return $this;
    }
 }
Daniel W.
  • 31,164
  • 13
  • 93
  • 151
2

It allows you to add custom setters and getters in case you want to add extra functionality, and also is sometimes used to track the "dirty" state (if an object has been changed since it was loaded from the DB).

It´s also due to the fact that PHP does not have a "native" syntax for read only properties.

Addition: I didn´t quite get my point across in my original answer that its in many cases due to how PHP works.

Consider this PHP example where we use metaprogramming to dynamically call custom setters.

class Foo {
    protected $bar;

    // use some metaprogramming magic to automatically call setter
    public function __set($key, $val){
        $setter = "set".ucfirst($key);
        if (method_exists($this, $setter)){
            $this->$setter($val);
        }
        else {
            throw new Exception("$key value cannot be set, looking for $setter in ".get_class($this));
        }
    }
    // enforce the Type of bar
    public function setBar(String $val){
        $this->bar = $val;
    }
}

$foo = new Foo();
// this should fail
$foo->bar = 12; 
// Catchable fatal error: Argument 1 passed to Foo::setBar() must be an instance of String, integer given

What I´m trying to get at here is that you are not a Bad Programmer for having public properties, but rather that most PHP frameworks dodge around the PHP object model that requires properties to be protected for inheritance and reflection to work in many cases.

max
  • 96,212
  • 14
  • 104
  • 165
1

Popular libraries which support their classes to be extended or inherited make their fields protected. This is concept of OOP that there must be abstraction and encapsulation in terms of data. Everyone shall not be allowed to directly access the data. Only member of a class shall access its data. This is reason fields are marked protected so that only inherited class's objects or same class's objects shall have access to data. All others must use get and set methods for reaching data. Keeping the code managed, clean and safe.

Murtaza Zaidi
  • 599
  • 3
  • 14
  • There is no golden rule that says that all data contained in an object must be protected or its "bad" OOP. Its more due to how the PHP object model works. Ruby for example has per property get / set / readonly methods and large libraries such as Mongoid and OpenRecord use public properties. – max Oct 05 '14 at 16:50
  • sorry ActiveRecord, not OpenRecord – max Oct 05 '14 at 18:21
  • Yes you are right there is no golden rule for everything must be protected. Its an option provided in OOP which is used for abstraction. There are and can be public and also private members in class depending on nature of data in class. – Murtaza Zaidi Oct 05 '14 at 18:41
  • I just realised that I was totally wrong. Ruby does not have public attributes, but all objects in ActiveRecord have getters/setters by default so in practice they are public. – max Oct 05 '14 at 19:42