16

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?

ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196
Starx
  • 77,474
  • 47
  • 185
  • 261
  • 5
    You don't seem to have grasped the concept of constructors. – BoltClock Mar 16 '11 at 07:26
  • @maria, yes kinda like that. @BoltClock, i understand the concepts of constructors well enough, but I am asking class variable initialization and methods for them. – Starx Mar 16 '11 at 07:30
  • BTW, Terminology: In OOP, a [Class variable](https://en.wikipedia.org/wiki/Class_variable) is a `static` member of a class; there is only **one** value to a "class variable", **shared** by all instances of that class. What you are showing are [Instance variables](https://en.wikipedia.org/wiki/Instance_variable), which in php are referred to as *properties*. – ToolmakerSteve Apr 22 '19 at 14:56

5 Answers5

14

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.

Riimu
  • 1,427
  • 8
  • 12
  • Point noted, but even if i use the 1st method, I can set the private variables as i like, this time it is only limited to few numbers. And using the 2nd method, if i set any new variables, then they will be public not private. – Starx Mar 16 '11 at 07:40
  • 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 are accessed via setters/getters, old functions can be changed to reflect changes inside the class, but code outside the class is hard to change. Your 2nd method also makes validation hard. – Riimu Mar 16 '11 at 07:50
  • very good point indeed. I think you should include this point in your answer. – Starx Mar 16 '11 at 08:03
  • Added it to the actual answer. – Riimu Mar 16 '11 at 08:10
8

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.

Ikke
  • 99,403
  • 23
  • 97
  • 120
  • So, then unavoidable class variables are better to be set using constructors? – Starx Mar 16 '11 at 07:33
  • 2
    Yup, that's where the constructor is for. To construct an object of the class to be able to do it's thing. – Ikke Mar 16 '11 at 07:57
1

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

  • I would agree with you, except in case of creating database model classes, where the member variables are usually protected or private and are accessed through public interface. Which is obviously one of many cases out there. – Starx Sep 18 '11 at 06:01
0

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
Radheshyam Nayak
  • 1,038
  • 3
  • 11
  • 20
  • No, `$x=$var1`, does not assign the value to `public $x`. And when you correct it, it will be similar to @Rinuwise's answer – Starx Mar 16 '11 at 07:43
  • This code is valid. @Starx - you misunderstand how properties (here, `$x`, `$y`) work in a class. You are thinking of the problem with reference to `global $x` in a function. Not the same. – ToolmakerSteve Apr 22 '19 at 14:51
  • 3
    @ToolmakerSteve, The code was later edited & corrected. :) – Starx Aug 21 '19 at 15:47
-1

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...

j_freyre
  • 4,623
  • 2
  • 30
  • 47
  • 3
    FWIW, while other languages support multiple dispatch, PHP does not. However, it does support default values for function calls, which usually works out pretty well. (This question is tagged PHP.) – Charles Mar 16 '11 at 07:28
  • @Starx - unfortunately, the code he shows is *not allowed* in php - compile error as soon as second one with same name is seen. – ToolmakerSteve Apr 22 '19 at 14:45