SubClass[] does not implicitly convert to SuperClass[], why?

rumbu via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Feb 20 04:58:01 PST 2015


On Friday, 20 February 2015 at 10:41:04 UTC, Jonathan M Davis 
wrote:
>
> class Super {}
> class Sub : Super {}
> class Sub2 : Super {}
>
> Sub[] subArr = createSubArr();
> Super[] superArr = subArr;
> superArr[2] = new Sub2;
>
> Now, all of a sudden, subArr[2] is a Sub2, when a Sub2 is not a 
> Sub. So, you
> would have broken the type system. The issue is called array 
> covariance.
> const avoids the problem, because you can't assign any of the 
> elements of
> the array.
>

A simple cast will always permit to destroy the type system 
entirely:

class Super {}

class Sub : Super {
	string alpha() { return "I am Sub"; }
	void SomeMethodNotFoundInSub2() { }
}

class Sub2: Super {
	string beta() { return "I am Sub2"; }
}

void foo(in Super[] sup)
{
	cast(Super)sup[0] = new Sub();
	cast(Super)sup[1] = new Sub2();
}


int main(string[] argv)
{

	Sub[] subArr = new Sub[2];
	foo(subArr);

	writeln(subArr[0]);
	writeln(subArr[1]); //look ma', my Sub[] array contains Sub2 
elements

	writeln(subArr[0].alpha());
	writeln(subArr[1].alpha()); //look ma', I'm calling beta of 
Sub2, because it has the same vtbl offset as alpha in Sub

	subArr[0].SomeMethodNotFoundInSub2(); //ok
	subArr[1].SomeMethodNotFoundInSub2(); // now we have an 
AccesViolation or maybe not, depending on Sub2 contents.
	
	getchar();
     return 0;
}

The problem is in fact the line below, and that kind of 
assignment must be checked at runtime instead of limiting compile 
time features that can be anyway circumvented, by throwing a 
specific exception.

sup[1] = new Sub2();






More information about the Digitalmars-d-learn mailing list