When to use Setters and Getters?

Asked

Viewed 3,152 times

16

I’m studying OOP and in the encapsulation part I had a question about when to use getters and setters, besides being able to validate the parameter passed, what is the usefulness of using?

I could just "take" the dice by __construct.

Example:

public function __construct ($valor1 , $valor2) { 
    $this->valor1 = $valor1;
    $this->valor2 = $valor2;
}

and

function setValor($valor){
    $this-valor = $valor;
}

3 answers

20

The visibility of a property (public, private and protected) are part of the Concept of Withholding Information, which is important to achieve greater data consistency.

For example, the code below:

class Db_Table {

    public $dbAdapter;

    public function __constructor( Db_Adapter $dbAdapter ) {

        $this -> dbAdapter = $dbAdapter;
    }
}

There’s nothing to stop Cletus from taking that code to do something like:

$this -> dbAdapter = 'Oi, eu sou o Goku!';

And send the code to space by defining an anime ending catchphrase on what should be an object that implements an interface to the database or extends that superclass.

This problem is solved by changing the visibility of the property and creating a Setter:

class Db_Table {

    private $dbAdapter;

    public function __constructor( Db_Adapter $dbAdapter ) {

        $this -> setAdapter( $adapter );
    }

    public function setAdapter( Db_Adapter $dbAdapter ) {

        $this -> dbAdapter = $dbAdapter;

        return $this;
    } 
}

And the code is now foolproof because the property Db_table::$dbAdapter invariably will be an instance of Db_adapter.

Also set the visibility of a property with private without a Setter defined makes it read-only in the context of the object.

However, it is possible yes manipulate the display property value private and protected through Reflection:

$obj = new Db_Table( new Db_Adapter );

try {

    $reflector = new ReflectionProperty( 'Db_Table', 'dbAdapter' );

    $reflector -> setAccessible( TRUE );

    $reflector -> setValue( $obj, 'Oi, eu sou Goku!' );

    var_dump( $reflector, $obj );

} catch( ReflectionException $e ) {

    echo $e -> getMessage();
}

Although Reflection does not serve for this. u.u'

Encapsulation is already a totally different animal. It involves the principle of code reuse (DRY - Don’t Repeat Yourself) that does not exist only in Object Orientation.

Procedurally, the simple fact of creating a function to store a repetitive piece of code is already a form of encapsulation.

The difference is that with Object Orientation we have inheritance, composition, polymorphism and all these strange words that raise the potential of encapsulation to the maximum of its potential.

Finally, the Validation the one you referred to, already covered by the examples, is only possible through a Setter because you can’t have polymorphism or even conditionality on public property. They accept whatever you pass to them.

Original Author: Henrique Barcelos

  • Thank you, I was able to understand the concept, but as such "you can’t have polymorphism or even conditionality on public property", I didn’t understand this part.

  • Public property works exactly like a tax. The left side gets the right side the way it was defined. Through a method you can specify that a certain property can only be an object that extends a certain class or implements a specific interface (polymorphism) or you can use some conditionals within the method so that the parameters can be of several different types.

  • If my answer or that of another user has solved your problem, remember to mark it as solved. Your doubt today may be someone else’s tomorrow. ;)

  • 1

    Autor Original: Henrique Barcelos. Wouldn’t it be nice to link or find the original text? I liked it :)

  • Yes, but it seems that since he went to Spain the blog died. He has a nice way of explaining complicated things. I think he’s got an account here, but no movement.

10

You use setters and getters to provide management of the attributes of your object. That is, you can change the variables of the object once created.

On the other hand, by encapsulating the attributes and not creating getter and Setter your object becomes fixed. That is, you cannot change the data once it has been created. You should pass the initial data in the constructor and after that they do not change anymore, since the attributes are encapsulated (private) and did not define any Setter, cannot change them. Normally, in languages like Java attributes are declared as final (in PHP I don’t know if we can declare variables like final, only in methods and classes, which in this case indicate something else) to indicate that they are fixed. These cases are often used to create immutable classes, which do not change state during their existence.

Another reason, as you said yourself, is to encapsulate the class data. One of the basic concepts of OO is precisely this, encapsulation. So if you leave your public property, it makes no sense to use getter and Setter, because there will be no encapsulation.

One of the most important points of getter and Setter, is the scalability. Imagine you have a class without getter and Setter and in several lines of your project you make use of the attribute directly, without the getter or Setter. When you need to do a maintenance you would have to change all these lines manually. Now if you had the getter and Setter, it would only be necessary to change the function getter or Setter, and the change would reflect in all its uses.

For the same reason, the use of getter and Setter is good for debug. Every time you need to debug this attribute within your project, just put a breakpoint in function getter or Setter, and not on each line where the property was used without the use of getter or Setter.

4

You’ll have people thinking, "I know what I’m doing, so I can leave the public attributes and that’s it!"

Getters and Setters go way beyond that, let’s see some utilities:

To make validations:

public function setIdade($idade) 
{
    if ($idade < 0 || $idade > 200) {
        throw new InvalidArgumentException('Idade invalida');
    }

    $this->idade = $idade;
}

To provide a fluent interface, return $this

public function execute()
{
    # executa alguma coisa
    return $this;
}

To organize the presentation of information

public function getInformacoes()
{
    $informacoes = array('nome' => $this->nome,
        'idade' => $this->idade,
        'sexo' => $this->sexo,
        'identificacao' => $this->identificacao);

    return $informacoes;     
}

In the constructor it must be passed what is necessary for that object to exist, for example, it does not make sense to have a birthday without a name and date of birth, so this data must be passed in the construction of the object, and not after.

Already the gifts received, will be added later or not

class Aniversariante
{
    private $nome;
    private $dataNascimento;
    private $presentes;

    public function __construct($nome, $dataNascimento)
    {
        $this->nome = $nome;
        $this->dataNascimento = $dataNascimento;
    }
    public function addPresentes(Convidado $presente)
    {
        $this->presentes[] = $presente;
    }
}

A mistake that many make, is to leave all attributes as private, and create getters and setters for all these, even without need. In this case, the attributes that are private practically become "public", since it is possible to read and write at all.

Getters and setters should only be created if there is need, otherwise attributes will be being exposed without necessity, leaking encapsulation.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.