C# 将ClassA.Method()调用为ClassB.Method(),但只影响ClassA值,这两个类都派生自同一基类
在本例中,我正在为浏览器构建一个自动化库。有一个基类叫做Mouse,派生类叫做robotmouse和HumanMouse 假设我将鼠标实例化为HumanMouse,但在一个特定场合,我希望它表现为机器人鼠标,例如,在需要它更快移动鼠标的部位,我尝试做的是: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 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回答了最新情况