Setting Variables on Constructor VS on the Class Definition

Setting variables on Constructor VS on the class definition

The advantage of initializing properties outside of the constructor is that someone reading your code will immediatly know its a default value.

Inconvenient is you cannot use every kind of data this way -- will not work with object instanciations, for instance, or with heredoc syntax, from what I recall.


I don't think there is much of a difference when it comes to performance -- anyway, there are probably lots of things that matter a lot more, in your application ;-)


Still, purely for fun, using the Vulcan Logic Disassembler :

With the first example of code (temp-2.php) :

<?php
class TestClass {
private $test_var = 'Default Value';
function __construct() {
}
}
$a = new TestClass();

You get these opcodes :

$ php -d extension=vld.so -d vld.active=1 temp-2.php
Branch analysis from position: 0
Return found
filename: /home/squale/developpement/tests/temp/temp-2.php
function name: (null)
number of ops: 11
compiled vars: !0 = $a
line # op fetch ext return operands
-------------------------------------------------------------------------------
2 0 EXT_STMT
1 NOP
7 2 EXT_STMT
3 ZEND_FETCH_CLASS :1 'TestClass'
4 EXT_FCALL_BEGIN
5 NEW $2 :1
6 DO_FCALL_BY_NAME 0
7 EXT_FCALL_END
8 ASSIGN !0, $2
9 RETURN 1
10* ZEND_HANDLE_EXCEPTION

Class TestClass:
Function __construct:
Branch analysis from position: 0
Return found
filename: /home/squale/developpement/tests/temp/temp-2.php
function name: __construct
number of ops: 4
compiled vars: none
line # op fetch ext return operands
-------------------------------------------------------------------------------
4 0 EXT_NOP
5 1 EXT_STMT
2 RETURN null
3* ZEND_HANDLE_EXCEPTION

End of function __construct.

End of class TestClass.

While, with the second example of code (temp-3.php) :

<?php
class TestClass2 {
private $test_var;
function __construct() {
$this->test_var = 'Default Value';
}
}
$a = new TestClass2();

You get those opcodes :

$ php -d extension=vld.so -d vld.active=1 temp-3.php
Branch analysis from position: 0
Return found
filename: /home/squale/developpement/tests/temp/temp-3.php
function name: (null)
number of ops: 11
compiled vars: !0 = $a
line # op fetch ext return operands
-------------------------------------------------------------------------------
2 0 EXT_STMT
1 NOP
8 2 EXT_STMT
3 ZEND_FETCH_CLASS :1 'TestClass2'
4 EXT_FCALL_BEGIN
5 NEW $2 :1
6 DO_FCALL_BY_NAME 0
7 EXT_FCALL_END
8 ASSIGN !0, $2
9 9 RETURN 1
10* ZEND_HANDLE_EXCEPTION

Class TestClass2:
Function __construct:
Branch analysis from position: 0
Return found
filename: /home/squale/developpement/tests/temp/temp-3.php
function name: __construct
number of ops: 7
compiled vars: none
line # op fetch ext return operands
-------------------------------------------------------------------------------
4 0 EXT_NOP
5 1 EXT_STMT
2 ZEND_ASSIGN_OBJ 'test_var'
3 ZEND_OP_DATA 'Default+Value'
6 4 EXT_STMT
5 RETURN null
6* ZEND_HANDLE_EXCEPTION

End of function __construct.

End of class TestClass2.

So, I'm guessing there is a bit of a difference... But not that important ^^

Up to you to interpret the opcodes -- but the funny thing is there is no trace of 'Default Value' in the first dump... interesting, actually ^^

Seems VLD cannot (or just doesn't) dump everything :-(

Java: constructor variables vs variables visible at the class-level

The variables on the class are called instance variables, meaning when you construct a new instance of Schedule it will have those variables that are specific to the instance.

the this keyword basically saying my instance, so for this example, the constructor takes a variable named clock and the Schedule class also has a variable named clock. So to distinguish between the two you use this keyword.

This this.clock = clock; set the variable clock on my instance to the value of clock passed to the constructor.

Setting variables in constructor vs definition

Is there any advantage or particular reason that you would set the variables in the definition of the "set" versus declaring them in the constructor?

No, and in fact, this is probably not what you want at all. This will make it impossible to set "break" or "cheese", as any call, such as bread = "rye";, would set it to "Amoroso" (if it worked, but will cause a StackOverflowException). Also note that trying to retrieve the value in your code will cause a StackOverflowException, and the property getter returns the property and not a backing field value.

You were likely thinking of this:

public class Cheesesteak
{
private string bread = "Amoroso";
public string Bread
{
get {return bread;}
set
{
bread = value;
}
}

// ...

The only advantage here is you're setting the "default" value where the field is defined, which can help with maintainability or readability in some cases, and even potentially eliminate the need for a defined constructor, which might reduce the overall length of code.

My initial guess is pattern 1 is shorter, but less efficient during compile.

In general, setting the fields inline vs. setting them in a constructor does not make this less efficient. The compiler will cause the type's actual constructor to set the fields first then run the constructor code, so both versions end up (for practical purposes) the same in terms of the compiled IL. This isn't a matter of efficiency, but rather of code readability and maintainability.

Note that, if you wanted the property to always be a constant (ie: Bread should always return "Amoroso"), you can just make the property have a getter and no setter:

public string Bread { get { return "Amoroso"; } }

I suspect this is not the case, but I thought I'd mention it as an option just in case it's what you intended.

Should I initialize variable within constructor or outside constructor

I find the second style (declaration + initialization in one go) superior. Reasons:

  • It makes it clear at a glance how the variable is initialized. Typically, when reading a program and coming across a variable, you'll first go to its declaration (often automatic in IDEs). With style 2, you see the default value right away. With style 1, you need to look at the constructor as well.
  • If you have more than one constructor, you don't have to repeat the initializations (and you cannot forget them).

Of course, if the initialization value is different in different constructors (or even calculated in the constructor), you must do it in the constructor.

Assigning a class variable in class definition versus at class instantiation

In this code snippet

int x = 0;
double y = 1.;

there is no assignments. There are initializations.

In this code snippet

Foo()
{
x = 0;
y = 1.;
}

there is indeed used the assignment operator.

In general for objects of complex types it can be 1) impossible (either the default constructor or the assignment operator is not available) or 2) requiring many resources because at first default constructors are called that create the objects and after that there are called assignment operators.

It is desirable to define constructors at least like for example

    Foo() : x( 0 ), y( 1 )
{
}

using mem-initializer lists.

Initialize class fields in constructor or at declaration?

My rules:

  1. Don't initialize with the default values in declaration (null, false, 0, 0.0…).
  2. Prefer initialization in declaration if you don't have a constructor parameter that changes the value of the field.
  3. If the value of the field changes because of a constructor parameter put the initialization in the constructors.
  4. Be consistent in your practice (the most important rule).

Typescript difference between setting variables in body vs constructor

Let's have a look at the generated javascript code (with no minification):

var Test1 = (function () {
function Test1() {
this.var1 = 5;
}
return Test1;
}());

var Test2 = (function () {
function Test2() {
this.var1 = 5;
}
return Test2;
}());

It's just the same.

As long as your instance variables are simply assigned hard coded primitive types you can safely assign them in the body of the class. If you have complicated logic or if you need one variable to be initialized before intializong another one it's better to do it in the constructor for the sake of clarity.

What's the difference between a class variable and a parameter in a constructor?

The class variable is the one defined by the class as a static field, and the parameter is the one defined by the method. It's just that simple. There are also instance variables (defined at the class level but not static) and local variables (defined within a method, but not as input parameters).

public class Foo {
private static String someName; // this is a class variable
private String someOtherName; // this is an instance variable

public Foo(String anotherName) { // anotherName is a constructor parameter
int yetAnother = 1; // yetAnother is a local variable
someOtherName = "foo"; // assign a value to someOtherName
}

These two variables are completely distinct. They don't even have to have the same type! The only complication in your example is that both variables happen to have the same name. When that happens, the compiler will favor the constructor parameter (or method parameter, or local variable) over the class variable. In order to "force" it to use the class variable, you prefix it with this..

The thing to keep in mind is that the two variables are totally separate, regardless of their names.

So this:

class NewClass {

private String Variable = "";

Public NewClass (String Variable)
{
NewClass.Variable = Variable;
}
}

is exactly the same as this:

class NewClass {

private String Variable = "";

Public NewClass (String someOtherVariableName)
{
NewClass.Variable = someOtherVariableName;
}
}

... and it's also exactly the same as this:

class NewClass {

private String Variable = "";

Public NewClass (String Var)
{
NewClass.Variable = Var;
}
}

The convention of using the same name for a parameter as for the class variable just means you don't have to come up with pointless variants on the variable name.



Related Topics



Leave a reply



Submit