Inheritance and arrays

Arafel er.krali at gmail.com
Mon Jul 3 12:11:28 UTC 2023


On 3/7/23 13:03, Rene Zwanenburg wrote:
> On Monday, 3 July 2023 at 09:50:20 UTC, Arafel wrote:
>> Is this a conscious design decision (if so, why?), or just a leak of 
>> some implementation detail, but that could eventually be made to work?
> 
> Besides the pointer adjustment problem mentioned by FeepingCreature, 
> it's an unsound conversion even with just class inheritance. Consider:
> 
> ```
> class A {}
> class B : A {}
> class C : A {}
> 
> void main()
> {
>    auto bArr = [new B()];
>    A[] aArr = bArr; // If this was allowed..
>    aArr[0] = new C(); // This would be a problem, because bArray would 
> now contain a C.
> }
> ```

This is a really good point. I just checked out of curiosity what Java 
does (because it's allowed there).

TIL it throws [an 
exception](https://docs.oracle.com/javase/8/docs/api/java/lang/ArrayStoreException.html) 
at runtime, which I guess is not a viable strategy for D.

Although when using interfaces, if I cast the individual class instances 
to interfaces, it should work, right?

Because then I'm storing the pointers to the interfaces, not to the 
actual class, so the arrays are actually different, and not two slices 
of the same array:


```
import std;

interface I { }
class C : I { }

void main() {
     C c = new C;
	I i = c;

	assert (c is i); // OK, took me a while to notice that "is" is smart 
enough.
     assert (cast (void *) c != cast (void *) i); // This is what we 
really care about.

	C[] cc = [ c ];
     I[] ii;
	ii = cc.map!( a => cast (I)a ).array;

	assert (ii[0] is c); // This can be unexpected, even if technically right!
     assert (cast (void*) ii[0] != cast (void*) c); // Now this is what 
we need.
}
```


More information about the Digitalmars-d-learn mailing list