In this example I am building an automation library for browsers. There is a base class called Mouse, and derived classes called RoboticMouse and HumanMouse.
Lets say I instantiate the mouse as HumanMouse but in one specific occasion I want it to behave as a RoboticMouse, for example, on parts where I need it to move the mouse faster, what I tried doing is:
Mouse m = new HumanMouse();
m.Move();
(m as RoboticMouse).Move();
But I get a NullReferenceException since the Mouse m was initialized as a HumanMouse and not a RoboticMouse.
I could do:
Mouse m = new HumanMouse();
m.Move();
m = new RoboticMouse(); m.Move();
But this way the values inside it would be re-initialized and I want to keep the state intact, for example, for tracking the mouse position.
EDIT: Simpler example:
This does not work as instance is ClassB, and throws null.
public class Program
{
public static void Run()
{
BaseClass instance = new ClassB();
instance.Increment();
Console.WriteLine(instance.Value);
(instance as ClassA).Increment();
Console.WriteLine(instance.Value);
Console.ReadLine();
}
}
class BaseClass
{
public int Value { get; set; }
public virtual void Increment()
{
Value++;
}
}
class ClassA : BaseClass
{
public override void Increment()
{
Value += 2;
}
}
class ClassB : BaseClass
{
public override void Increment()
{
Value += 4;
}
}
If I follow the suggestion given making ClassB inherit from ClassA:
class ClassB : ClassA
{
public override void Increment()
{
Value += 4;
}
}
And try to cast it:
public static void Run()
{
BaseClass instance = new ClassB();
instance.Increment();
Console.WriteLine(instance.Value);
(instance as ClassA).Increment();
Console.WriteLine(instance.Value);
Console.ReadLine();
}
It still runs ClassB version of the method...
The compiler does not know how to conver from HumanMouse
to RoboticMouse
.
When you are using new
you are creating effectively a new reference with new values, so it makes sense to see what you see.
Two ways around it. If a HumanMouse
is indeed a RoboticMouse
, then extend the HumanMouse
from the RoboticMouse
If the HumanMouse
is castable to a RoboticMouse
, then you can declare how the cast is made by using the user-defined-conversion-operators .
Edit based on question edits
Let me give you an example with animals.
Let's say that ClassA
is an animal and ClassB
is a Cat. So the Cat
extends the animal and set a new behavior for the Move
function.
The cat will always be an animal, but not every animal is a cat. That's why
// This works
Animal a = new Cat();
// This does not work
Cat a = new Animal();
Now when you assign a cat to an animal and you have overriden the Move
function, that means that the cat will always move as a cat whether or not you access it as an animal. You can't cast a cat to an animal as it is already an animal. (cat as Animal)
does nothing.
Same way you can't cast classB
to classA
since B is already an A and will always behave as a B.
public abstract class Mouse {
public int x {get; set;}
public int y {get; set;}
public Mouse(x,y) {
this.x = x;
this.y = y;
}
public virtual void Move() {
this.x++;
this.y++;
}
public virtual void Move(x, y) {
this.x+= x;
this.y+= y;
}
}
public class HumanMouse: Mouse {
// whatever
public HumanMouse(): base(1,1) {
}
}
public class RoboticMouse: Mouse {
public static int
// whatever
public RoboticMouse(): base(2,2) {
}
}
Mouse m = new HumanMouse();
m.Move();
m.Move(1,2);
// or
Mouse m2 = new RoboticMouse();
m.Move();
m.Move(m2.x,m2.y);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.