Bug 1228 – Class invariants should not be called before the object is fully constructed
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
Other
OS
Linux
Creation time
2007-05-11T13:04:00Z
Last change time
2014-02-16T15:22:06Z
Assigned to
bugzilla
Creator
onlystupidspamhere
Comments
Comment #0 by onlystupidspamhere — 2007-05-11T13:04:28Z
The spec should state whether invariants hold only after the constructor has finished or not. http://www.webber-labs.com/research/paste01.ps contains some discussion about class invariants in Java, and might be helpful.
The following code shows how D currently checks invariants even before the class has been fully constructed. IMO invariants should hold only after the constructor has finished and there is a valid reference to the object.
Code:
import tango.io.Stdout;
class foo {
this() {
Stdout("entering constructor").newline;
bar();
Stdout("leaving constructor").newline;
}
void bar() {
Stdout("method bar()").newline;
}
invariant {
Stdout("invariant").newline;
}
}
void main() {
auto a = new foo();
}
Output:
entering constructor
invariant
method bar()
invariant
leaving constructor
invariant
Comment #1 by braddr — 2007-05-11T14:25:52Z
Invariants are checked after every public member function's execution as well, so the behavior you're seeing at least meets the spec. Now, I can see some arguments for not having invariants checked until construction is complete, but that'd be a change in documented behavior.
Comment #3 by onlystupidspamhere — 2007-05-12T04:11:27Z
(In reply to comment #2)
> Sound reasonable to me, too. You can always refactor to:
>
> class foo {
>
> this() {
> Stdout("entering constructor").newline;
> barInternal();
> Stdout("leaving constructor").newline;
> }
>
> void bar() {
> barInternal();
> }
>
> private void barInternal() {
> Stdout("method bar()").newline;
> }
>
> invariant {
> Stdout("invariant").newline;
> }
> }
This slows down the release build since at least DMD doesn't inline member functions. Yes, this is a design decision and I'm not sure which one is better.
Comment #4 by bugzilla — 2007-07-01T00:38:19Z
Since the invariant is called at the start of public or
exported members, such members should not be called from
constructors. I'll update the documentation to indicate this.
Comment #5 by onlystupidspamhere — 2007-07-01T03:05:48Z
(In reply to comment #4)
> Since the invariant is called at the start of public or
> exported members, such members should not be called from
> constructors. I'll update the documentation to indicate this.
Good, updating the docs works for me.