簡體   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