Thread overview | |||||
---|---|---|---|---|---|
|
November 12, 2012 Base Class Hitting Derived Class Invariant | ||||
---|---|---|---|---|
| ||||
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 |
November 12, 2012 Re: Base Class Hitting Derived Class Invariant | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vijay Nayar | 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
|
November 12, 2012 Re: Base Class Hitting Derived Class Invariant | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vijay Nayar | 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.
|
Copyright © 1999-2021 by the D Language Foundation