C#,像方法一样实现'静态抽象'

时间:2009-05-05 06:58:41

标签: c# static abstract

我最近遇到了一个问题,我似乎需要一个'静态抽象'方法。我知道为什么这是不可能的,但我怎样才能解决这个限制呢?

例如,我有一个抽象类,它有一个描述字符串。由于此字符串对于所有实例都是通用的,因此它被标记为static,但我想要求从此类派生的所有类都提供它们自己的Description属性,因此我将其标记为abstract:

abstract class AbstractBase
{
    ...
    public static abstract string Description{get;}
    ...
}

当然不会编译。我想过使用接口但接口可能不包含静态方法签名。

我应该只是非静态的,并且总是得到一个实例来获取特定于类的信息吗?

有什么想法吗?

8 个答案:

答案 0 :(得分:31)

你不能。

这样做的地方是属性。

例如

[Name("FooClass")]
class Foo
{
}

答案 1 :(得分:6)

如果你不介意推迟实现以合理地实现Description属性,你可以简单地执行

public abstract string ClassDescription {get; } 
// ClassDescription is more intention-revealing than Description

实现类会做类似的事情:

static string classDescription="My Description for this class";
override string  ClassDescription { get { return classDescription; } }

然后,你的班级必须遵守描述的合同,但你要留给他们理智地做。没有办法以面向对象的方式指定实现(除了通过残忍的,脆弱的黑客攻击)。

但是,在我看来这个描述是类元数据,所以我更喜欢使用其他人描述的属性机制。如果您特别担心多次使用反射,请创建一个反映您所关注的属性的对象,并在Type和Description之间存储字典。这将最小化反射(除了运行时类型检查,这不是那么糟糕)。字典可以存储为通常需要此信息的任何类的成员,或者,如果域中的客户端需要它,则通过单例或上下文对象存储。

答案 2 :(得分:5)

将静态和抽象结合起来有点毫无意义,是的。静态背后的想法是,为了使用有问题的成员,不需要提供类的实例;但是对于abstract,我们期望一个实例是一个提供具体实现的派生类。

我可以理解为什么你想要这种组合,但事实是唯一的结果就是拒绝使用'this'或任何非静态成员。也就是说,父类将规定派生类的实现中的限制,即使在调用抽象或“静态抽象”成员之间没有潜在的区别(因为两者都需要一个具体的实例来确定要使用的实现)

答案 3 :(得分:5)

如果它是静态的,那么变量只有一个实例,如果我们可以在派生类中使用静态变量完成你想要完成的任务,我看不出继承是否有意义。就个人而言,我认为你会尽量避免实例变种。

为什么不只是经典的方式?

abstract class AbstractBase
{
    protected string _Description = "I am boring abstract default value";
}

class Foo : AbstractBase {

     public Foo() {
       _Description = "I am foo!";
     }
}

答案 4 :(得分:3)

如果必须在实例上调用它,则不是静态的。

如果你没有在实例上调用它,那么就没有多态性(即就语言而言,ChildA.Description与ChildB.Description完全无关。)

答案 5 :(得分:2)

一种可行的解决方法是在Generics的帮助下在基类中定义派生类的Singleton。

import System;

public abstract class AbstractBase<T>
    where T : AbstractBase<T>, new()
{
    private static T _instance = new T();

    public abstract string Description { get; }
    public static string GetDescription()
    {
        return _instance.Description;
    }
}

public class DerivedClass : AbstractBase<DerivedClass>
{
    public override string Description => "This is the derived Class";
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(DerivedClass.GetDescription());
        Console.ReadKey();
    }
}

诀窍是告诉您AbstractBase<T>有关如何实施DerivedClass的一些详细信息:

  • where T: new()可以创建,因此可以创建一个Singleton实例
  • 它源于where T : AbstractBase<T>,因此它知道会有Description的实现

这种方式_instance包含可以在静态方法Description中调用的GetDescription()字段。 这会强制您覆盖Description中的DerivedClass,并允许您使用DerivedClass.GetDescription()

调用其值

答案 6 :(得分:2)

你可以...

在抽象类中...

 protected abstract InWindow WindowInstance { get; set; }

在派生类中...

    private static InWindow _instance;


    protected override InWindow WindowInstance
    {
        get => _instance;
        set => _instance = value;
    }

答案 7 :(得分:0)

你可以制作&#34;摘要&#34;基本方法抛出Exception,然后开发人员被警告&#34;如果他试图在子类上调用此方法而不覆盖。

缺点是可能会扩展类而不使用此方法。然后参考提供的其他答案。