I have an classes:
class AClass : CClass
class BClass : CClass
And I need to use them in follow code:
The POJO class:
class SomeObject<T> where T : CClass
T clazz;
setClass(T clazz){
this.clazz = clazz;
.....
controller class:
class ObjectExecutor{
private SomeObject<CClass> someObject;
public ObjectExecutor execute(SomeObject<CClass> so){
someObject = so; //exception when so - is the instance of AClass
return this;
}
public void build(){
....
}
}
so when I try to implement it:
SomeObject<AClass> soA = new....
soA.execute(soA) //exception point
.build()
In result I get the exception: can't cast AClass to CClass
So I need use something like:
class ObjectExecutor{
private SomeObject someObject; //without <> signature
..... ....
but 'c#' compiler does not allow this way.
screenshots:
I have two classes that extends between:
Interface:
Implementing:
And point where issue is occurred: 1.
2.
Error:
Arg "1": the type conversion from "MyTest.Terkin.ActionElement<Ranorex.Button>" in "MyTest.Terkin.ActionElement<Ranorex.Adapter>" is impossible (CS1503) - C:\Users\Valeryi\Documents\Ranorex\RanorexStudio\MyTest\Recording1.UserCode.cs:60,23
It's the matter of variances and covariances
After discussing your problem inside the comment section I've realized that you need the covariance here as you are assigning more derived class than originally specified. Pineapple.Given
waits ActionElement<Adapter>
but you are trying to pass ActionElement<Button>
and Button
is deriving from Adapter
. It means we need covariance here. As I already told you in the comment section, you can achieve covariance with generics using out
keyword. Note that only interface and delegate type parameters can be specified as variant so in order to achieve that we have to create an interface and use it whenever we want covarience to be applied. Here's the code (your code from screenshots that I slightly modified):
class Actions { }
class Adapter { }
class Button : Adapter { }
// covariant generic interface
interface IActionElement<out T> where T : Adapter
{
T GetAdapter();
}
// covariant generic interface implementation
class ActionElement<T> : IActionElement<T> where T : Adapter
{
T adapter;
public T GetAdapter()
{
return adapter;
}
public ActionElement(T adapter)
{
this.adapter = adapter;
}
}
class Pineapple
{
IActionElement<Adapter> actionElement;
Queue<Actions> queue;
// note that I'm using the IActionElement interface here. Not the class that implements the interface like you do
public Pineapple Given(IActionElement<Adapter> adapter)
{
actionElement = adapter;
queue = new Queue<Actions>();
return this;
}
}
class Program
{
static void Main(string[] args)
{
// now it works
Pineapple pineapple = new Pineapple();
var pineappleClone = pineapple.Given(new ActionElement<Button>(new Button()));
}
}
It's a vice versa case, when you need to assign less derived class than originally specified.
class BaseClass { }
class DerivedClassA : BaseClass { }
class DerivedClassB : BaseClass { }
interface ISomeObject<in T> where T : BaseClass
{
void SetClass(T clazz);
}
class SomeRealObject<T> : ISomeObject<T> where T : BaseClass
{
T obj;
public void SetClass(T obj)
{
this.obj = obj;
}
}
And then you can use it like you this:
ISomeObject<DerivedClassA> soA = new SomeRealObject<BaseClass>();