2

我想要一些类,它们都扩展一个基本抽象类。

然后,我想要每个对象都存储这些类的子集并调用它们实现的方法。

所以我想 - 我对存储的对象什么都不做,所以让我们将这些类设为静态,我不会在存储对象上浪费内存,只是引用静态类,所以我可以调用静态函数。问题是 - 我该怎么做?

对于那些喜欢代码的人,这是我需要的:

public static abstract class A {
    public static abstract void F();
}

public static class B : A {
    public static override void F() {
        ...
    }
}
// Class Storage of course does NOT work, its just here to illustrate what I need
public class Storage {
    private List<A> list;
    public void AddElement(A element) {
        list.Add(element);
    }
    public void DoStuff() {
        foreach(A element in list)
            element::F();
    }
}

有没有办法做这样的事情?还是针对此类问题的不同解决方案?

4

3 回答 3

3

不,你不能那样做。您尝试执行的操作存在许多问题:

  1. 您不能使用静态类型作为类型参数——例如List<A>.
  2. 您不能使用静态类型作为方法参数——例如AddElement(A element).
  3. 您不能将静态类型抽象化,因为无法从它继承。
  4. 即使在非静态类中,也不能使静态方法抽象,因为它不能被覆盖。

从您描述问题的方式来看,我可以看到这里不需要静态类型或静态方法。只需创建一个简单的抽象类并从中继承:

public abstract class A {
    public abstract void F();
}


public class B : A {
    public override void F() {
        ...
    }
}

public class Storage {
    private List<A> list;
    public void AddElement(A element) {
        list.Add(element);
    }
    public void DoStuff() {
        foreach(A element in list)
            element.F();
    }
}

或者,您可以创建一个List<Type>并使用反射来调用这些类型的静态方法。例如:

public static class A {
    public static void F() { ... }
}
public static class B {
    public static void F() { ... }
}

List<Type> typeList = new List<Type> { typeof(A), typeof(B) };
foreach(var type in typeList)
{
    type.GetMethod("F").Invoke(null, null); 
}

但是使用反射会比使用直接方法调用要慢,并且您将失去使用此方法的所有类型安全性(除非您自己编写类型检查)。

于 2013-07-31T17:22:03.933 回答
1

pswg 的回答显示了处理您给我们的代码的正确方法,但听起来您想要做的是调用方法列表。这些方法没有关联数据,因此您想将它们设为静态类。为什么不使用动作?

public class Storage {
    private Action list;
    public void AddElement(Action element) {
        list.Add(element);
    }
    public void DoStuff() {
        foreach(Action element in list)
            element();
    }
}

然后,您可以将方法添加到存储中,如下所示:

public void DefineStoredFunctions(Storage s)
{
    s.AddElement(() => { first function F });
    s.AddElement(() => { another function F });
    s.AddElement(() => A.F()); //or just call function defined on A
    s.AddElement(B.F); //or get rid of lambda altogether
    //and so on...
}

编辑:如果这不是你想要的,你应该采取其他答案的方法并使用普通对象

于 2013-07-31T17:29:59.203 回答
0

这个想法有很多问题:

  • 静态类只有一个实例,只能在“静态上下文”中访问。您不能定义静态类,然后将其添加为列表的元素。

  • 静态类不能从任何对象继承,也不能从任何对象继承(它是隐式的)。

  • 因为继承不适用于静态,所以虚拟或抽象重写方法的概念也不适用于静态。

  • 静态对象的代码和任何静态实例状态(字段、属性)只使用稍微少一点的内存,就像普通对象一样。

只需使用普通对象即可。“过早的优化是计算机编程中万恶之源——无论如何,大部分都是罪恶的根源”。我想不出比我正在回答的问题更好的例子来说明该陈述的真实性,其中极少的内存节省被用来证明试图打破面向对象设计的基本规则(即尽量减少静态状态的使用) .

如果要获取对象的实例,请确保您拥有的实例与其他所有人的实例相同(换句话说,只允许存在一个实例),但仍将其视为对象的实例,看看在单例模式。C# 中的 Singleton 可以从其他类继承,也可以从其他类继承,可用的实例正是如此,因此您可以将它传递给其他不必关心它的代码(例如您的列表),然而您仍然可以从您不介意使用静态访问器的任何地方获取该实例,并且您可以强制您只有一个。

于 2013-07-31T17:29:17.017 回答