簡體   English   中英

C#:如何從派生類的靜態方法調用基類的靜態方法?

[英]C#: How do I call a static method of a base class from a static method of a derived class?

在C#中,我有基類Product和派生類Widget。

產品包含靜態方法MyMethod()。

我想從靜態方法Widget.MyMethod()調用靜態方法Product.MyMethod()。

我不能使用base關鍵字,因為它只適用於實例方法。

我可以顯式地調用Product.MyMethod(),但是如果我稍后將Widget更改為從另一個類派生,我必須修改該方法。

C#中有一些類似於base的語法允許我從派生類的靜態方法中調用基類的靜態方法嗎?

static方法基本上是從面向對象的概念中回退的方法。 因此,它們在繼承層次結構方面不是很靈活,並且不可能直接執行這樣的操作。

我能想到的最接近的是using指令。

using mybaseclass = Namespace.BaseClass;

class MyClass : mybaseclass {

  static void MyMethod() {  mybaseclass.BaseStaticMethod();  }

}

使用反射調用靜態方法與調用實例方法完全相同,只是為實例傳遞null。 你需要FlattenHierarchy,因為它是在祖先中定義的。

var type = assy.GetType("MyNamespace.MyType");
MethodInfo mi = type.GetMethod("MyStaticMethod", 
  BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
mi.Invoke(null, null);

進一步的閱讀和思考讓我和其他人一樣回答問題:為什么要使用這樣的靜態方法? 您是否正在嘗試進行函數式編程,如果是這樣,為什么不使用lambda表達式呢? 如果您希望多態行為具有共享狀態,則實例方法會更好。

它可以做到,但我不推薦它。

public class Parent1
{
    public static void Foo()
    {
        Console.WriteLine("Parent1");
    }
}

public class Child : Parent1
{
    public new static void Foo()
    {
        Type parent = typeof(Child).BaseType;
        MethodInfo[] methods = parent.GetMethods();
        MethodInfo foo = methods.First(m => m.Name == "Foo");
        foo.Invoke(null, null);
    }
}

可以辦到:

public class Parent1
{
    protected static void Foo()
    {
        Console.WriteLine("Parent1");
    }
}

public class Child : Parent1
{
    public static void Foo()
    {
        return Parent1.Foo();
    }
}

可用於單元測試受保護的靜態方法(例如)。

首先,如果你擔心重新教育一個類,那么你可能做錯了繼承。 繼承應該用於建立“is-a”關系,而不僅僅是促進代碼重用。 如果您需要單獨重用代碼,請考慮使用委托,而不是繼承。 我想你可以在子類型和它的父類之間引入一個中間類型,但我會讓這種可能性驅動我的設計。

其次,如果您需要使用基類中的功能但是擴展它並且用例需要靜態方法,那么您可能需要考慮使用一些外部類來保存功能。 我心目中的經典案例是工廠模式。 實現Factory模式的一種方法是通過Factory Methods,一個構造該類實例的類的靜態方法。 通常構造函數受到保護,因此工廠方法是從外部構建類的唯一方法。

在繼承層次結構中使用工廠方法重用的一種方法是將公共代碼放在受保護的方法中,並從工廠方法調用該方法,而不是直接從子類型工廠方法調用基類工廠方法。 更好的實現可能使用相同的技術,但將Factory方法移動到Factory類並使用構造函數邏輯(內部現在,而不是私有),可能與初始化方法結合使用,以創建對象。 如果您繼承的行為是來自類的外部(decryption / validation / etc),則可以使用Factory中的共享方法(或組合)來允許在Factory方法之間重用。

在不知道使用靜態方法的目標的情況下,很難給出確切的方向,但希望這會有所幫助。

靜態方法不是多態的,所以你想要做的是不可能的。

試圖找到一種將靜態方法視為多態的方法是可能的但很危險,因為語言本身並不支持它。

一些建議:

這很簡單。 比使用別名,反射等簡單得多。也許在新增的.NET,IDK中它變得更容易,但這種方法非常好。 與實例方法一樣,訪問基本方法不需要使用base ,它是可選的,通常在繼承和基類具有相同名稱的方法時是必需的。 即使沒有base關鍵字,您也可以訪問基類的靜態方法,就像它們在您調用的類中一樣。 我只在從派生類的靜態方法調用基本靜態方法時測試了這個。 如果從實例方法調用靜態方法,則可能無法工作。

public class BaseThings
{
    protected static void AssertPermissions()
    {
        //something
    }
}

public class Person:BaseThings
{
    public static void ValidatePerson(Person person)
    {
        //just call the base static method as if it were in this class.
        AssertPermissions();            
    }
}

考慮到靜態方法不會在實例數據中中繼...你應該有一個靜態的“MyMethod”,它根據參數或類似的東西表現不同。

請記住,在一個類中定義的靜態方法只是一種對代碼進行排序的方法......但是如果將該方法放在其他地方它也是一樣的...因為它不會在放置它的對象上進行中繼。

編輯:我認為你最好的選擇是明確地使用Product.MyMethod ...如果你認為...你的Widget可能不會改變它的基礎...而且在這種情況下它是一個小的改變在代碼中。

靜態方法是“類級”方法。 它們旨在成為適用於特定類的所有實例的方法。 因此,這種方法的繼承沒有意義,因為它會改變應用於類實例的含義。 例如,如果您循環遍歷產品集合(某些Widget,某些不是)並在每個產品上調用MyMethod,則調用的方法將由類的實例確定。 這違反了靜態方法的目的。

你可以通過簡單地完全不使用靜態方法來做你想要更干凈的事情,因為在你的例子中,似乎MyMethod並不適用於所有的Product實例。 但是,您可以使用像“IMyMethod”這樣的接口類來實現與描述相同的效果。 這種方法仍然沒有使用靜態方法。 我想我不需要靜態方法。 為什么要使用靜態方法開始?

暫無
暫無

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

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