简体   繁体   中英

Which is the better approach to initialize php properties?

Here are two way to initialize class variables.

1st Method

class Test {
    private $var1;
    private $var2;

    public function Test($var1,$var1) {
        $this->var1 = $var1;
        $this->var2 = $var2;
    }
}
$objTest = new Test("value1","value2");

2nd Method

class Test {
    private $var1;
    private $var2;

    public function _set($var, $value) {
        $this->$$var = $value
    }
}
$objTest = new Test();
$objTest->_set('var1','value1');
$objTest->_set('var2','value2');

Now, these both methods are valid, but I would like to know which one in better in what conditions? What are pros and cons of sticking with one method only?

In your example, the second method is highly risky. If you give the variable name as an argument, you basically give the code the access to set all private variables from outside the class. What is the point of having private variables if you allow them to be set freely like that?

Additionally, the point of encapsulation in OOP, is that the inner workings of a class are not transparent to the code outside the class. Your second method breaks this encapsulation and thus part of the point of OOP, as the code outside the class has to be aware of the inner workings of the class, like the name of the variables. What happens if you later choose to change the variable names? All the code breaks. If they were accessed via setters/getters, old functions could be changed to reflect changes inside the class, but code outside the class would be difficult to change. In addition to that, the second method makes the validation of the values hard.

You should use the first method, especially if setting the class variables is necessary for operation. However, if you feel that some default values can be allowed for the attributes, you can just take advantage of PHP's default argument values like:

class Test {
    private $var1;
    private $var2;

    public function Test($var1 = 'defaultValue', $var1 = 'defaultValue') {
        $this->var1 = $var1;
        $this->var2 = $var2;
    }
}
$objTest = new Test();

Anyway, if the values must be initialized by the code, then you should definitely force them to be passed in the constructor. If default values are allowed, then either initialize the values in constructor with separate setters for the variables or just default argument values like in the provided example. It is, however, bad practice to expect the code to set critical values via setters after the constructor has been called.

If those variables are necessary for the operation of the class, you would beter use the first method. That way you can ensure they are set when the class is created.

I wonder why you have defined your variables as private in the first place. Private members exist for the class itself rather than for use through a public interface. It may be keeping track of some value, which a magic setter method (__set) can change, at any time in the program, as you have it in your second example. If you need your variables to be private (for class only access) then a constructor function __construct($var1,$var2) or __construct($var1=" defaultvalue ",$var2=" defaultvalue "), so in keeping with your first example.

It would depend on your anticipated states, which you would have planned in state/activtiy diagrams.

Hope that helps

What about this

class A{

    public $x;
    public $y;
    function A($var1=10,$var2=15){   //the default value for the class
        $this->x=$var1;  
        $this->y=$var2;

    }
}

$object_of_A= new A(20,30);  //if you do not want to change the default value then
                               //pass no arguments

My mind is that you should combine both methods.

Properties that are unavoidable must be present in a construct method.

For properties that are optional, you should define default value in the construct then create getter/setter.

And you can create multiple construct methods like for database, in generally, you have:

myConstructor($dsn)
myConstructor($dsn, $username, $password)
myConstructor($dsn, $username, $password, $port)
myConstructor($dsn, $username, $password, $port, $options)

Then in the "bottom" construct you will set $options then call the "upper" construct that will set the $port and will call "upper" construct... etc...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM