繁体   English   中英

将 ClassA.Method() 调用为 ClassB.Method() 但只影响 ClassA 值,两个类都源自相同的 BaseClass

[英]Calling a ClassA.Method() as ClassB.Method() but only affecting ClassA values, both classes are deriving from the same BaseClass

在这个例子中,我正在为浏览器构建一个自动化库。 有一个名为 Mouse 的基类,以及名为 RoboticMouse 和 HumanMouse 的派生类。

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

Mouse m = new HumanMouse();
m.Move();
(m as RoboticMouse).Move();

但是我得到一个 NullReferenceException,因为 Mouse 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 版本......

编译器不知道如何从HumanMouseRoboticMouse

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

绕过它的两种方法。 如果HumanMouse确实是RoboticMouseHumanMouse扩展RoboticMouse

如果HumanMouse可转换为RoboticMouse ,则您可以使用user-defined-conversion-operators声明如何进行转换

根据问题编辑进行编辑

让我给你举个动物的例子。

假设ClassA是一只动物, ClassB是一只猫。 所以Cat扩展了动物并为Move函数设置了一个新的行为。

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

// This works
Animal a = new Cat();
// This does not work
Cat a = new Animal();

现在,当您将猫分配给动物并覆盖Move函数时,这意味着无论您是否以动物的身份访问它,猫都将始终以猫的身份移动。 你不能把猫扔给动物,因为它已经是动物了。 (cat as Animal)什么都不做。

同样,您不能将classBclassA因为 B 已经是 A 并且将始终表现为 B。

编辑 2:可能的解决方案

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM