Reputation: 43
In the following code sample, milk
is initialized by a constructor, and egg
isn't. milk.spill()
does not segfault, but egg.crack()
does. What is the difference between the two ways of initialzing an instance variable? Why is the former correct while the latter causes segfaults?
import std.stdio;
void main() {
auto k = new Kitchen();
k.pollute();
}
class Kitchen {
Milk milk;
Egg egg = new Egg();
this() {
milk = new Milk();
}
void pollute() {
writeln("spilling milk");
milk.spill();
writeln("cracking egg");
egg.crack();
}
}
class Milk {
bool spilt = false;
void spill() { spilt = true; }
}
class Egg {
bool cracked = false;
void crack() { cracked = true; }
}
Upvotes: 4
Views: 80
Reputation: 25605
So the difference between the two ways is when the code is run. When you initialize in a constructor, the code is run at runtime, when each new object is made. When you do it directly on the class member, the object is actually constructed at compile time and referenced statically.
What that means in your example is that there's a new Milk object created for each Kitchen object. When you run new Kitchen
, the constructor runs, meaning you get a new Milk
as well.
Egg
is different. It is in a static context, so that initializer is run at compile time - only once. What that means is that there is only one Egg
shared among all the new Kitchen
s. The variable itself isn't static, if you assigned it to a new Egg
sometime after making a new Kitchen
, it would only affect that instance of the kitchen, but the object it refers to immediately is.
So if you just set it to new Egg
outside the constructor and never replace it, any modifications you do to that egg will be visible across all instances of the kitchen - after you crack the egg, then do another new Kitchen
, it will already have a cracked egg!
Upvotes: 5