简体   繁体   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

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 .编译器不知道如何从HumanMouseRoboticMouse

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确实是RoboticMouseHumanMouse扩展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.同样,您不能将classBclassA因为 B 已经是 A 并且将始终表现为 B。

Edit 2: Possible solution编辑 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.

相关问题 ClassA中的方法是否可能由ClassB中的事件触发? - Is it possible for a method in ClassA to be triggered by an event in ClassB? 测试ClassA中的方法是否已从ClassA中的另一个方法调用 - Test if method in ClassA has been called from another method in ClassA 从ClassA转换为ClassB的设计指南 - Design guidelines for converting from ClassA to ClassB 有效地创建List <ClassB> 从列表 <ClassA> ? - efficiently creating List<ClassB> from List<ClassA>? 当ClassB从ClassA继承时,如何将List <ClassB>转换为List <ClassA>? - How to cast List<ClassB> to List<ClassA> when ClassB inherits from ClassA? 将ClassA中的事件处理程序添加到ClassB中调用的事件中 - Add event handler from ClassA to an event called in ClassB ClassB继承ClassA。 如何检查ClassA objA是否为ClassB类型,然后将objA转换为ClassB? - ClassB inherits ClassA. How do I check if ClassA objA is of ClassB type and then convert objA to ClassB? “ClassA c =新的ClassB`声明可能吗? - Is `ClassA c = new ClassB` declaration possible? 将C#通用约束指定为ClassA或ClassB? - Specify a C# Generic Constraint to be of ClassA OR ClassB? 无法从“方法组”转换为 Func <list<classa> &gt; 实例化新任务时</list<classa> - cannot convert from 'method group' to Func<List<ClassA>> when instantiating a new Task
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM