I am trying to create a generic class where the type parameter class has a reference to the generic ‘parent’
Something like this:
public class A<T> where T : B {
T item;
public A<T> (GameObject item) {
this.item = item;
this.item.GetComponent<T>().parent = this;
}
}
public class B {
A<B> parent;
}
This obviously does not work, since I cannot assign an object of type A<T> to a variable of type A<B>, even though T has to be derived from B. Polymorphism of the type parameter sadly doesn’t mean that the generic types are polymorphic. Is it possible to do something like this, or am I SOL?
Not sure exactly what you are trying to achive here, so not sure if this helps or not:
A< T > and A< R > are completely different classes, as far as the compiler is concerned. So even if R derives from T, and T derives from B, the two version of the A< > classes remain unrelated.
That being said and assuming class R derives from class T: calls like
A<T> variable=new A(someInitialRvalue)
and
A<T> variable=new A(someInitialTvalue)
would both be perfectly valid.
Or, if you made the member “item” public:
A<T> genericClassInstance;
genericClassInstance.item = new T();
and
A<T> genericClassInstance;
genericClassInstance.item = new R();
would also be a valid assignment
And, if we had these two variables defied:
A<T> tBasedValue;
A<R> rBasedValue;
tBasedValue=rBasedValue; //this is NOT valid;
tBasedValue.item=rBasedValue.item; //this IS valid
There where T:B syntax simply requires R and T, in the examples, be descendants of class B. I like to look at it as simply a handy way for generic class programmers to limit what classes they can be implemented on, by forcing the compiler to generate errors when a “user programmer” attempts to use it with the wrong type of class. Though functionally, it also allows the generic class to reference members of the B class, which is upon consideration, I guess the more important part).
I found a solution, although I am not sure that I like it:
public interface IA {}
public class A<T> : IA where T : B {
T item;
public A<T> (GameObject item) {
this.item = item;
this.item.GetComponent<T>().parent = this;
}
public void DoSomething(T item) {
//do something
}
}
public class B {
IA parent;
public void CallToParent() {
((A<B>) parent).DoSomething(this);
}
}
Edit: I know I could pull the DoSomething(T item) function into the interface and avoid the cast, but then I would have to use B there instead of the generic type parameter T, and I would loose a bit of safety (theoretically it would then be possible to pass an object of a separate class that also derives from B to the function)