I got two classes.
- busiObj(created from ancient flat files)
- key(provides means to tell busiObjs apart)
key has a c'tor that takes a busiObj
public key(busiObj foo)
{
bar = foo.someThing;
[...]
}
I want to create the key in the c'tor of the busiObj
public busiObj(...)
{
myKey = new key(this);
[...]
}
However: Why on earth does it work?
I firmly expected the compiler to throw something like:
"You cannot reference an object that is currently being made, duh".
So: How is it that I can reference an object while it is still being constructed?
-
3The object might not be finished being constructed, but we know where it will be (in memory) when it is, hence we can get a reference to that location.George Duckett– George Duckett2014年07月01日 07:30:52 +00:00Commented Jul 1, 2014 at 7:30
-
@GeorgeDuckett then is it safe to do this call, given that I initialized all parts of myObj that the c'tor of key uses? Also: Is this bad practice (it somehow feels so)?Mark– Mark2014年07月01日 07:33:39 +00:00Commented Jul 1, 2014 at 7:33
2 Answers 2
So: How is it that I can reference an object while it is still being constructed?
Presumably Because it's useful (though in a dangerous way) for exactly the scenario you describe, so the language designers decided to allow it.
Technically, it's not a problem at all: while the object is being constructed, its memory must already be allocated, so you can certainly have a reference to it.
-
Just as @George Duckett also lines out. It feels wrong though.Mark– Mark2014年07月01日 07:35:44 +00:00Commented Jul 1, 2014 at 7:35
-
4@Mark: It's safe to do inasmuch as there is no undefined behaviour; the worst you can encounter (if you make a mistake) is object states (mostly null references) that are not possible according to your class contract. It's not a good practice because in maintaining that code, it's easy to lose track of the fact that you're handling a partially initialized object and introduce weird bugs.Michael Borgwardt– Michael Borgwardt2014年07月01日 07:46:20 +00:00Commented Jul 1, 2014 at 7:46
-
Instantiate an object without a constructor is intriguing. It means an object exists before the constructor is called.radarbob– radarbob2014年07月04日 01:28:40 +00:00Commented Jul 4, 2014 at 1:28
Why this happens is because this is a reference to the memory area that your object is currently occupying. Since instructions in the code are executed sequentially, you already have your object in some state that's being referenced when you get to the point of calling the key() method.
Although this is possible, the entire approach is wrong. The methods inside an object should only change the state of the instance, not the state of other instances of that object. Your example works because it roughly translates into the code below at runtime:
public busiObj() {
myKey = new key();
[...]
}
public key()
{
bar = foo.someThing;
[... use "this" here to reference your object internally ...]
[... other stuff here ...]
}
-
...not the state of other instances of that object where am I doing that? I am not changing one busiObj from another.Mark– Mark2014年07月01日 08:37:01 +00:00Commented Jul 1, 2014 at 8:37
-
In your implementation the key() method gets a busiObj object as a parameter - but you're under no obligation to send the current instance to the method. Assuming you work on the foo object that you get, if that object is not this then you will essentially work in your method with another object. Since you are sending the this reference from the constructor, the interpreter takes care of translating the reference to your current object in key(), but this will not alwais be the case.Thyamarkos– Thyamarkos2014年07月01日 08:40:52 +00:00Commented Jul 1, 2014 at 8:40
-
ahh, that's what you mean. I am actually reading already initialized properties from the passed, half-finished busiObj, not manipulating its state though.Mark– Mark2014年07月01日 08:43:10 +00:00Commented Jul 1, 2014 at 8:43