簡體   English   中英

C#“繼承”靜態方法?

[英]C# “Inheriting” Static Methods?

這是我想要完成的一個例子:

abstract class DoSomething
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You asked the abstract class to work. Too bad.");
    }
}

class InspireMe : DoSomething
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You are amazing.");
    }
}

class InsultMe : DoSomething
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You aren't worth it.");
    }
}

class Program
{
    static void Main()
    {
        DoSomething worker = InsultMe;
        worker.DoWhateverItIsThatIDo(); 

        worker = InspireMe;
        worker.DoWhateverItIsThatIDo();
    }
}

我來自Python背景,其中方法本身可以是變量,然后可以調用它。 看起來C#沒有這個概念,但我正在努力完成類似的事情。

我的想法是我想要一個可以是抽象類型的變量,這樣就可以在其中存在許多不同類型的子類型。 所有這些亞型都有一定的方法。 我希望能夠將任何這些子類型分配給抽象類型的此變量,然后調用子類型中存在的靜態方法。

在C#術語中,我希望能夠將分配給變量,而不是類的實例 ,然后調用該類的靜態方法。

工廠聽起來可能在正確的道路上,但我不確定工廠本身如何能夠生成這些類的引用(而不是創建實例)。

我可以重做這個來使用實例,但是假設我想要有靜態方法來生成每種類型的類,所有類都仍然從基類型繼承。

我覺得最有可能做到這一點 - 有人可以提出建議嗎?

在您描述的意義上,您不能將類用作C#中的變量。 反射本質上允許您將類型視為變量並動態調用它們上的靜態成員,但它將是混亂的而不是類型安全的。

通過使用單例模式,您基本上可以完成您要執行的操作:

interface IDoSomething
{
    void DoWhateverItIsThatIDo();
}

class DoSomething : IDoSomething
{
    private DoSomething() {}
    internal static readonly IDoSomething Instance;
    static DoSomething()
    {
        Instance = new DoSomething();
    }

    public void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You asked the abstract class to work. Too bad.");
    }
}

class InspireMe : IDoSomething
{
    private InspireMe() {}
    internal static readonly IDoSomething Instance;
    static InspireMe()
    {
        Instance = new InspireMe();
    }

    public void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You are amazing.");
    }
}

class InsultMe : IDoSomething
{
    private InsultMe() {}
    internal static readonly IDoSomething Instance;
    static InsultMe()
    {
        Instance = new InsultMe();
    }

    public void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You aren't worth it.");
    }
}
class Program
{
    static void Main()
    {
        IDoSomething worker = InsultMe.Instance;
        worker.DoWhateverItIsThatIDo(); 

        worker = InspireMe.Instance;
        worker.DoWhateverItIsThatIDo();
    }
}

除了類和實例之外,您真正想要的是對具有特定簽名的方法的引用,在您的情況下為void ()

雖然無法為變量分配靜態類,但可以以類型安全的方式將方法分配給變量。 在C#中,您通常使用ActionFunc的重載,具體取決於方法簽名的外觀。

為了使這更有趣,讓我們假設您想引用類似int Foo(string, bool) ,只需使用Func<string,bool,int>類型的變量,並為其分配任何具有此簽名的方法。

解決問題的代碼大致如下:

class DoSomething
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You asked the abstract class to work. Too bad.");
    }
}

class InspireMe
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You are amazing.");
    }
}

class InsultMe
{
    static void DoWhateverItIsThatIDo()
    {
        Console.WriteLine("You aren't worth it.");
    }
}

class Program
{
    static void Main()
    {
        Action worker = InsultMe.DoWhateverItIsThatIDo;
        worker(); 

        worker = InspireMe.DoWhateverItIsThatIDo;
        worker();
    }
}

解決方法可能是在基本抽象類中聲明Action類型的屬性,該屬性包含要調用的方法。 然后通過調用基類構造函數在派生類實例化期間初始化此屬性:

abstract class DoSomething
{
    public Action DoWhateverItIsThatIDo { get; set; }

    protected DoSomething() { DoWhateverItIsThatIDo = DoSomething.DoIt; }

    protected DoSomething(Action whatAction)
    {
        DoWhateverItIsThatIDo = whatAction;
    }

    protected static void DoIt()
    {
        Console.WriteLine("You asked the abstract class to work. Too bad.");
    }
}

class InspireMe : DoSomething
{
    public InspireMe() : base(InspireMe.DoIt) { }

    private static void DoIt()
    {
        Console.WriteLine("You are amazing.");
    }
}

class InsultMe : DoSomething
{
    public InsultMe() : base(InsultMe.DoIt) { }

    private static void DoIt()
    {
        Console.WriteLine("You aren't worth it.");
    }
}

class DoWhatBaseClassDoes : DoSomething
{
    public DoWhatBaseClassDoes() : base() {}
}

class Program
{
    static void Main(string[] args)
    {
        DoSomething worker = new InsultMe();
        worker.DoWhateverItIsThatIDo();

        worker = new InspireMe();
        worker.DoWhateverItIsThatIDo();

        // In this case base class method is invoked
        worker = new DoWhatBaseClassDoes();
        worker.DoWhateverItIsThatIDo();
    }
} 

C#而不是Java都不能讓你覆蓋靜態基類方法。

但是,您似乎仍在使用對象的引用(您的worker變量),那么為什么不使用非靜態類方法呢?

(如果這不是您打算做的,請澄清。)

我不是100%確定這是你想要的,但我寫了一個模擬C#中Prototypal繼承的庫。

public class Foo: ProtoObject {}
public class Bar: Foo {}

dynamic myFoo = new Foo();
dynamic yourFoo = new Foo();
dynamic myBar = new Bar();

myFoo.Prototype.Name = "Josh";
myFoo.Prototype.SayHello = new Action(s => Console.WriteLine("Hello, " + s));

yourFoo.SayHello(myBar.Name); // 'Hello, Josh'

這當然涉及大量使用dynamic關鍵字,這可能沒用,因為你丟失了大量的編譯時檢查。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM