digitalmars.D.learn - Base Class Hitting Derived Class Invariant
- Vijay Nayar (41/41) Nov 11 2012 I was working on a little project when I encountered something
- Jonathan M Davis (6/9) Nov 11 2012 Don't call virtual functions inside the constructor if you don't want an...
- Tobias Pankrath (2/43) Nov 12 2012 Make init private and don't override it.
I was working on a little project when I encountered something 
odd.  Essentially a base class contains some data and a derived 
class needs a slice of that data.  Certain properties of this 
slice must be maintained, so the derived class has an invariant.
What happens is that if the base class, even in the constructor, 
calls a function that is overridden in the derived class, the 
invariant gets invoked.  This can make initialization quite 
difficult.
Below is a stripped down example of this.
void main() {
   auto b = new B([1, 2, 3, 4, 5, 6]);
}
class A {
   uint[] data;
   this(uint[] data) {
     this.data = data;
     init();  // This ends up calling B.init() and fails the 
invariant!
   }
   void init() {
     // Do some checking.
   }
}
class B : A {
   uint[] dataSlice;
   invariant() {
     assert(dataSlice !is null);
   }
   this(uint[] data) {
     super(data);
     dataSlice = data[3..$];
   }
   override void init() {
     // Do more checking;
     super.init();
   }
}
If the base class constructor needs to occur before the derived 
class constructor, is there a good way to solve this without 
getting rid of the invariant?
  - Vijay
 Nov 11 2012
On Monday, November 12, 2012 04:32:51 Vijay Nayar wrote:If the base class constructor needs to occur before the derived class constructor, is there a good way to solve this without getting rid of the invariant?Don't call virtual functions inside the constructor if you don't want any functions to invoke the derived class' invariant. If you need something done in the derived class, then do it in the derived class' constructor rather than a virtual function called by the base class constructor. - Jonathan M Davis
 Nov 11 2012
On Monday, 12 November 2012 at 03:32:52 UTC, Vijay Nayar wrote:
 I was working on a little project when I encountered something 
 odd.  Essentially a base class contains some data and a derived 
 class needs a slice of that data.  Certain properties of this 
 slice must be maintained, so the derived class has an invariant.
 What happens is that if the base class, even in the 
 constructor, calls a function that is overridden in the derived 
 class, the invariant gets invoked.  This can make 
 initialization quite difficult.
 Below is a stripped down example of this.
 void main() {
   auto b = new B([1, 2, 3, 4, 5, 6]);
 }
 class A {
   uint[] data;
   this(uint[] data) {
     this.data = data;
     init();  // This ends up calling B.init() and fails the 
 invariant!
   }
   void init() {
     // Do some checking.
   }
 }
 class B : A {
   uint[] dataSlice;
   invariant() {
     assert(dataSlice !is null);
   }
   this(uint[] data) {
     super(data);
     dataSlice = data[3..$];
   }
   override void init() {
     // Do more checking;
     super.init();
   }
 }
 If the base class constructor needs to occur before the derived 
 class constructor, is there a good way to solve this without 
 getting rid of the invariant?
  - Vijay
Make init private and don't override it.
 Nov 12 2012








 
  
  
 
 Jonathan M Davis <jmdavisProg gmx.com>
 Jonathan M Davis <jmdavisProg gmx.com> 