[英]Calling a ClassA.Method() as ClassB.Method() but only affecting ClassA values, both classes are deriving from the same BaseClass
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.
有一个名为 Mouse 的基类,以及名为 RoboticMouse 和 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:假设我将鼠标实例化为 HumanMouse,但在一个特定场合,我希望它表现得像 RoboticMouse,例如,在我需要它更快地移动鼠标的部分,我尝试做的是:
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.但是我得到一个 NullReferenceException,因为 Mouse m 被初始化为 HumanMouse 而不是 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.这不起作用,因为实例是 ClassB,并抛出 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:如果我遵循使 ClassB 从 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...它仍然运行该方法的 ClassB 版本......
The compiler does not know how to conver from HumanMouse
to RoboticMouse
.编译器不知道如何从
HumanMouse
为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.当您使用
new
您正在有效地创建一个具有新值的新引用,因此查看您所看到的内容是有意义的。
Two ways around it.绕过它的两种方法。 If a
HumanMouse
is indeed a RoboticMouse
, then extend the HumanMouse
from the RoboticMouse
如果
HumanMouse
确实是RoboticMouse
, HumanMouse
扩展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 .如果
HumanMouse
可转换为RoboticMouse
,则您可以使用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.假设
ClassA
是一只动物, ClassB
是一只猫。 So the Cat
extends the animal and set a new behavior for the Move
function.所以
Cat
扩展了动物并为Move
函数设置了一个新的行为。
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.现在,当您将猫分配给动物并覆盖
Move
函数时,这意味着无论您是否以动物的身份访问它,猫都将始终以猫的身份移动。 You can't cast a cat to an animal as it is already an animal.你不能把猫扔给动物,因为它已经是动物了。
(cat as Animal)
does nothing. (cat as Animal)
什么都不做。
Same way you can't cast classB
to classA
since B is already an A and will always behave as a B.同样,您不能将
classB
为classA
因为 B 已经是 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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.