C#:如何从派生类的静态方法调用基类的静态方法?

时间:2009-03-02 17:24:59

标签: c# inheritance static base derived-class

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

产品包含静态方法MyMethod()。

我想从静态方法Widget.MyMethod()调用静态方法Product.MyMethod()。

我不能使用base关键字,因为它只适用于实例方法。

我可以显式调用Product.MyMethod(),但如果我稍后将Widget更改为从另一个类派生,我必须修改该方法。

C#中有一些类似于base的语法允许我从派生类的静态方法中调用基类的静态方法吗?

9 个答案:

答案 0 :(得分:18)

static方法基本上是一种从面向对象的概念中回退的方法。因此,它们在继承层次结构方面不是很灵活,并且不可能直接做这样的事情。

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

using mybaseclass = Namespace.BaseClass;

class MyClass : mybaseclass {

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

}

答案 1 :(得分:4)

可以这样做,但我不推荐它。

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);
    }
}

答案 2 :(得分:4)

使用反射调用静态方法与调用实例方法完全相同,只是为实例传递null。你需要FlattenHierarchy,因为它是在祖先中定义的。

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

进一步阅读和思考让我和其他人一样回答问题:为什么要使用这样的静态方法?您是否正在尝试进行函数式编程,如果是这样,为什么不使用lambda表达式呢?如果你想要具有共享状态的多态行为,那么实例方法会更好。

答案 3 :(得分:3)

可以这样做:

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

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

可用于单元测试受保护的静态方法(例如)。

答案 4 :(得分:2)

首先,如果你担心重新教育一个类,那么你可能做错了继承。继承应该用于建立“is-a”关系,而不仅仅是促进代码重用。如果您需要单独重用代码,请考虑使用委托,而不是继承。我想你可以在子类型和它的父类之间引入一个中间类型,但我会让这种可能性推动我的设计。

其次,如果您需要使用基类中的功能但是扩展它并且用例需要静态方法,那么您可能需要考虑使用一些外部类来保存功能。我心目中的经典案例是工厂模式。实现Factory模式的一种方法是通过Factory Methods,一个构造该类实例的类的静态方法。通常构造函数是受保护的,因此工厂方法是从外部构建类的唯一方法。

在继承层次结构中使用工厂方法重用的一种方法是将公共代码放在受保护的方法中,并从Factory方法调用该方法,而不是直接从子类型调用基类Factory方法工厂方法。更好的实现可能使用相同的技术,但将Factory方法移动到Factory类并使用构造函数逻辑(内部现在,而不是私有),可能与初始化方法结合使用,以创建对象。如果您继承的行为来自类外部(decryption / validation / etc),则可以使用Factory中的共享方法(或组合)来允许在Factory方法之间重用。

在不知道使用静态方法的目标的情况下,很难给出确切的方向,但希望这会有所帮助。

答案 5 :(得分:1)

静态方法不是多态的,所以你想做的事情是不可能的。

试图找到一种将静态方法视为多态的方法是可能的但很危险,因为语言本身并不支持它。

一些建议:

答案 6 :(得分:0)

考虑到静态方法不会在实例数据中中继...你应该有一个静态的“MyMethod”,它根据参数或类似的东西表现不同。

请记住,在一个类中定义的静态方法只是一种对代码进行排序的方法......但是如果将该方法放在别处,它就是相同的...因为它不会在放置它的对象上进行中继

编辑:我认为你最好的选择是明确地使用Product.MyMethod ......如果你认为......你的Widget可能不会改变它的基础...而且在这种情况下,它是代码的微小变化。

答案 7 :(得分:0)

静态方法是“类级”方法。它们旨在成为适用于特定类的所有实例的方法。因此,这种方法的继承没有意义,因为它会改变应用于类实例的含义。例如,如果您循环遍历产品集合(某些Widget,某些不是)并在每个产品上调用MyMethod,则调用的方法将由类的实例确定。这违反了静态方法的目的。

你完全可以通过简单地不使用静态方法来做更干净的事情,因为在你的例子中,似乎MyMethod并不适用于所有的Product实例。但是,您可以使用像“IMyMethod”这样的接口类来实现与描述相同的效果。这种方法仍然没有使用静态方法。我想我不需要静态方法。为什么要使用静态方法开始?

答案 8 :(得分:0)

这很简单。比使用别名,反射等简单得多。也许在新增的.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();            
    }
}