Getters and Setters can only "walk" together?

Asked

Viewed 450 times

16

I am studying object orientation and am having some doubts in the encapsulation part. For example:

Class Url {

    private $url;

    public function setUrl($url) {

        if (filter_var($url, FILTER_VALIDATE_URL)) {
            $this -> url = $url;
        } else {
            $this->url= false;
        }
    }

    public function getUrl(){

        return $this->url;

    }


}

How I need to validate the URL I created this Setter, since it is a better practice than doing the validation in the constructor, correct?

I’ll wear it out of class, but this one getter no, so I really need to create both? Why could I use the variable $url in the class context, since I will only use it within the same class.

Taking advantage of this question, I understood that I would only create the Setter/getter if I were to change the value of the variable throughout the application, correct? Otherwise I could simply "build it" in the constructor? Example:

public function __construct ($url) {

    $this->url = $url;

}
  • I improved the wording of the question but it is worth it to you to review it because in one part you say you will use the value outside the class and in another moment you say you will not need the getter because the value will only be used within the class. I have not touched this part (to add a nay to the first statement), not to radicalize its intention.

  • I meant that I will use Setter outside the class, but I could directly use the $url variable, without the getter, got it?

2 answers

13


In Object Orientation getters and setters participate in the Principle of Withholding Information, which ensures that a property is available for reading or writing only in certain circumstances:

  • Private: Only who defined
  • Protected: Who defined and who to extend
  • Public: Everyone

However, both getters how much setters are optional. And this allows you to simulate read-only and even write-only properties (if there is any practical application for this) which, until now, cannot be done automatically at the level of interpretation:

In your example, set visibility of the property Url::$url as private ensures that no one can change its value directly.

If she had visibility public, this could occur:

$url = new Url;

$url -> url = 'Oi, eu sou Goku!';

And anything that relies on a valid URL would fail.

Therefore, you have to ensure that only Urls are informed as a value for this argument because through a Setter, you can validate.

If this value needs to be read in the context of the instance, you should add a getter. But if that argument can’t be altered in the same context, you don’t need and shouldn’t even have a Setter because once defined the URL it must be kept the same until the object is destroyed manually or at the end of the Request.

However, although the constructor of an object serves to build the object (Doh) he must not do everything alone.

The ideal is to delegate the task of validating and assigning value to the property through a Setter.

But you’re contradicting yourself!

Yes, it may look like this, but just as properties have configurable visibility, so are they for methods, so you can have a method specifically created to validate and set a value to that property, but not available externally:

class Url {

    private $url;

    public function __construct( $url ) {

        $this -> setUrl( $url );
    }

    private function setUrl( $url ) {

        if( filter_var( $url, FILTER_VALIDATE_URL ) === FALSE ) {

            throw new InvalidArgumentException(

                sprintf( '%s is not a valid URL', $url )
            );
        }

        $this -> url= $url;
    }

    public function getUrl(){
        return $this -> url;
    }
}

Notice, too, the difference in this code compared to yours. You accepted an invalid URL which forces you to manually check that this value is a valid URL when your class needs to use the value of that property again and again and again.

And that defeats the purpose of a Setter which is precisely to ensure that the past information is reliable.

In this example, if the URL does not pass the validation I trigger a Invalidargumentexception, a specific natively available exception to be used when a given argument is invalid for the purpose of who defined it.

Good studies :)

  • Thanks, Very good the answer, I managed to get the idea :)

  • 1

    Just a warning rs, Sprintf does not work because you assigned to the variable false, so it does not show the URL, but already fixed, Thank you very much :))

12

No, you can use either of the two separately as per your need. Good practice is the one you need and is correct.

If you won’t use the getter publicly, do not create it.

In fact if you also don’t need to assign value to a property publicly, which makes a lot of sense if you’re not going to have one getter, then there’s no point in creating a Setter. If you only need to initialize a class member, and eventually validate, do it in the constructor.

Class Url {
    private $url;

    public function __construct ($url) {
        if (filter_var($url, FILTER_VALIDATE_URL)) {
            $this -> url = $url;
        } else {
            $this->url= false;
        }
    }
}

I put in the Github for future reference.

Of course it depends on how you want to use this instance variable $url. I imagine that anything that manipulates it within the class does not depend on the validation placed in the constructor, otherwise it would be interesting to use a method that serves as an intermediary to access the variable. In general you can control its state more reliably within the class and do not need validation.

  • I understood, but I was a little confused by the explanation at the end, if I already saw it in the constructor why would I need to create a method for it? then, wouldn’t it be better to create Setter/getter right away to use within the class? Thank you!

  • Exactly, it doesn’t usually make sense to have these methods in the case you’re demonstrating. What could happen in a hypothetical case of a complex class that keeps manipulating some data and at the risk of putting it in an invalid state. Then it might be interesting to have a method that mediates this to validate every time it is changed. But take this as something rare. This method would be the Setter.

Browser other questions tagged

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