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