Maxime Picard
Maxime Picard

Reputation: 683

Should we access protected properties directly or with getters?

Should we access protected properties directly or with getters in PHP ?

I have two classes with one is the daughter of the other. In the mother, I declare certain properties as protected and I generate all getters for my properties. So, I can access and define those properties directly or via the getters, but I don't know if there is a better solution.

Example :

class Mother {

    private $privateProperty;
    protected $protectedProperty;
    public $publicProperty;

    /*** Private property accessors ***/   

    public function setPrivateProperty($value)
    {
        $this->privateProperty = $value;
    }

    public function getPrivateProperty()
    {
        return $this->privateProperty;
    }

    /*** Protected property accessors ***/   

    public function setProtectedProperty($value)
    {
        $this->protectedProperty = $value;
    }

    public function getProtectedProperty()
    {
        return $this->protectedProperty;
    }
}

class Child extends Mother {

    public function showProtectedProperty() {
        return $this->getProtectedProperty();   // This way ?
        return $this->protectedProperty;        // Or this way ?
    }

    public function defineProtectedProperty() {
        $this->setProtectedProperty('value');   // This way ?
        $this->protectedProperty = 'value';     // Or this way ?
    }
}

In the example, I know I can't access/set directly the private property, and that it's useless for public properties. But I can use both ways for the protected property. So, are there any standard to use ?

Upvotes: 6

Views: 2675

Answers (3)

deceze
deceze

Reputation: 522015

You shouldn't even think about properties as having "a getter/setter". These two are different things. Properties store state, getters return values, setters modify the object state. Sometimes these may have very direct 1:1 correlations, but they need not have.

In fact, if all your setter does is $this->foo = $foo and the getter does return $this->foo, make it a public property to begin with! For all intents and purposes it already is. There's no point to having functions dress up this property, they do not in fact add any value.

For the sake of discussion, imagine a class like this:

class Foo {

    protected $timestamp;

    public function setStartTime($int) {
        $this->timestamp = new DateTime("@$int");
    }

    public function getElapsedTime() {
        return $this->timestamp->diff(new DateTime);
    }

}

This more clearly illustrates the disconnect between state, state modification and value return. The "setter" accepts an integer, the property stores a DateTime object, and the "getter" returns a DateInterval object. They don't really have anything to do with one another.

To bring this back around to your original question: If you know what state the property represents and when/how it may be modified and what rules the class expects this property state to adhere to, you may touch the property directly. If, however, you do not know a lot about the inner workings of the class and just want to interact with its public interface to get its results, use the accessor methods.

Upvotes: 3

Matt S
Matt S

Reputation: 15364

I answered a similar question a while back on Programmers.SE:

I won't say which is better or worse, because that partly depends on your situation (in my opinion). But consider that your getters and setters may change implementation later, and bypassing them would skip that logic.

For example, what happens if you add a "dirty" flag to some setter fields later? By calling your setters in your internal code you'll set the dirty flag without changing any other code. In many situations this would be a good thing.

You might need special rules, like maybe initialization code should skip using setters. The most important thing is to pick an appropriate policy in your project and stick to it for consistency.

Upvotes: 3

IceFire
IceFire

Reputation: 4138

Best encapsulation is accomplished when you indeed use getters and setters also along a class hierarchy. This means: Attributes should be private and getters/setters are protected (if not public).

For example, if you want to log access to certain attributes, want to add a filter method or another check, the whole mechanism would be removed, if you just accessed those attributes in the derived class.

(Of course, there are situations where you would just make attributes public to make code shorter and because you know that the class is really just a data-holder... In that case, however, those attributes would still not be protected but simply public)

Upvotes: 4

Related Questions