C# 将ClassA.Method()调用为ClassB.Method(),但只影响ClassA值,这两个类都派生自同一基类

C# 将ClassA.Method()调用为ClassB.Method(),但只影响ClassA值,这两个类都派生自同一基类,c#,object,casting,polymorphism,state,C#,Object,Casting,Polymorphism,State,在本例中,我正在为浏览器构建一个自动化库。有一个基类叫做Mouse,派生类叫做robotmouse和HumanMouse 假设我将鼠标实例化为HumanMouse,但在一个特定场合,我希望它表现为机器人鼠标,例如,在需要它更快移动鼠标的部位,我尝试做的是: Mouse m = new HumanMouse(); m.Move(); (m as RoboticMouse).Move(); 但是我得到了一个NullReferenceException,因为鼠标m被初始化为HumanMouse而不是

在本例中,我正在为浏览器构建一个自动化库。有一个基类叫做Mouse,派生类叫做robotmouse和HumanMouse

假设我将鼠标实例化为HumanMouse,但在一个特定场合,我希望它表现为机器人鼠标,例如,在需要它更快移动鼠标的部位,我尝试做的是:

Mouse m = new HumanMouse();
m.Move();
(m as RoboticMouse).Move();
但是我得到了一个NullReferenceException,因为鼠标m被初始化为HumanMouse而不是RoboticMouse

我可以做到:

Mouse m = new HumanMouse();
m.Move();
m = new RoboticMouse(); m.Move();
但是这样里面的值会被重新初始化,我想保持状态不变,例如,为了跟踪鼠标位置

编辑: 更简单的例子:

这不起作用,因为实例是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;
    }
}
如果我遵循所给出的建议,让ClassB继承ClassA:

class ClassB : ClassA
{
    public override void Increment()
    {
        Value += 4;
    }
}
试着投下它:

public static void Run()
    {
        BaseClass instance = new ClassB();

        instance.Increment();
        Console.WriteLine(instance.Value);

        (instance as ClassA).Increment();
        Console.WriteLine(instance.Value);

        Console.ReadLine();
    }

它仍然运行该方法的ClassB版本…

编译器不知道如何从
HumanMouse
转换到
Robotmouse

当您使用
new
时,您有效地创建了一个具有新值的新引用,因此查看所看到的内容是有意义的

有两种方法。如果
HumanMouse
确实是
robotmouse
,则从
robotmouse
扩展
HumanMouse

如果
HumanMouse
可投射到
robotmouse
,则可以使用声明投射方式

根据问题编辑进行编辑

让我举一个动物的例子

假设
ClassA
是一种动物,
ClassB
是一只猫。因此,
Cat
扩展了动物并为
Move
功能设置了新的行为

猫永远是动物,但不是每一种动物都是猫。这就是为什么

// This works
Animal a = new Cat();
// This does not work
Cat a = new Animal();
现在,当您将一只猫指定给一只动物,并且您已经覆盖了
Move
功能时,这意味着无论您是否以动物身份访问猫,猫都将以猫的身份移动。你不能把猫扔给动物,因为它已经是动物了<代码>(猫是动物)什么都不做

同样,您不能将
classB
强制转换为
classA
,因为B已经是A,并且将始终表现为B

编辑2:可能的解决方案
编译器不知道如何从
HumanMouse
转换到
robotmouse

当您使用
new
时,您有效地创建了一个具有新值的新引用,因此查看所看到的内容是有意义的

有两种方法。如果
HumanMouse
确实是
robotmouse
,则从
robotmouse
扩展
HumanMouse

如果
HumanMouse
可投射到
robotmouse
,则可以使用声明投射方式

根据问题编辑进行编辑

让我举一个动物的例子

假设
ClassA
是一种动物,
ClassB
是一只猫。因此,
Cat
扩展了动物并为
Move
功能设置了新的行为

猫永远是动物,但不是每一种动物都是猫。这就是为什么

// This works
Animal a = new Cat();
// This does not work
Cat a = new Animal();
现在,当您将一只猫指定给一只动物,并且您已经覆盖了
Move
功能时,这意味着无论您是否以动物身份访问猫,猫都将以猫的身份移动。你不能把猫扔给动物,因为它已经是动物了<代码>(猫是动物)什么都不做

同样,您不能将
classB
强制转换为
classA
,因为B已经是A,并且将始终表现为B

编辑2:可能的解决方案
唯一有效的情况是
HumanMouse
扩展
robotmouse
,而这反过来又扩展了
Mouse
。但是,您可以创建
鼠标
来接受参与者。它可以同时接受
人类
机器人
,并且您可以通过演员对鼠标实例进行操作-这更接近于将鼠标投射到某物上的实际场景。您可以通过一个简单的示例查看我的编辑吗@Zorgoz唯一有效的情况是
人类鼠标
扩展
机器人鼠标
,而机器人鼠标则依次扩展
鼠标
。但是,您可以创建
鼠标
来接受参与者。它可以同时接受
人类
机器人
,并且您可以通过演员对鼠标实例进行操作-这更接近于将鼠标投射到某物上的实际场景。您可以通过一个简单的示例查看我的编辑吗@佐尔戈兹人类老鼠是老鼠,机器人老鼠是老鼠。我的选择是什么?编辑:尝试从Robotmouse派生HumanMouse,并强制转换(m为Robotmouse)。Move();仍然运行HumanMouse.Move();如果它们是可浇铸的(可互换的),则使用用户定义的转换运算符将一个转换为另一个。如果您想让它作为
机器人鼠标
移动,那么在
人类鼠标
中创建一个辅助
移动机器人
,并调用它。您能用一个更简单的示例查看我的编辑吗@Athanasios KatarasCheck更新了答案,解释了为什么您的代码不能按预期工作。确实如此,但在概念上没有意义。我将更新您的问题的可能解决方案。HumanMouse是鼠标,RoboticMouse是鼠标。我的选择是什么?编辑:尝试从Robotmouse派生HumanMouse,并强制转换(m为Robotmouse)。Move();仍然运行HumanMouse.Move();如果它们是可浇铸的(可互换的),则使用用户定义的转换运算符将一个转换为另一个。如果您想让它作为
机器人鼠标
移动,那么在
人类鼠标
中创建一个辅助
移动机器人
,并调用它。您能用一个更简单的示例查看我的编辑吗@Athanasios KatarasCheck回答了最新情况