我创建了一个抽象类,我们称之为FooBarizable
,即2个clases(在实践中更多),Foo
和Bar
的父级。现在,我有一个FooBarizableManager
来管理Foo
和Bar
个类,具体取决于他的类型。从FroobarizableManager
开始,我想打电话给getFooBarizables()
。让我们看看结构:
FooBarizable.cs:
public abstract class FooBarizable{
public string Name { get; set; }
public static IEnumerable<FooBarizable> GetFooBars(){
throw new NotImplementedException();
}
}
Foo.cs:
public class Foo : FooBarizable{
public static IEnumerable<FooBarizable> GetFooBars(){
return API.getFoos();
}
}
Bar.cs:
public class Bar : FooBarizable{
public static IEnumerable<FooBarizable> GetFooBars(){
return API.getBars();
}
}
FooBarizableManager.cs:
public class FooBarizableManager {
private Type type;
public FooBarizableManager(Type _t){
this.type = _t;
}
public void showFooBarizables(){
MethodInfo method = type.GetMethod("GetFooBars");
IEnumerable<FooBarizable> FooBars = (IEnumerable<FooBarizable>)method.invoke(null, null);
show(FooBars);
}
...
}
所以,我的问题是我想从管理器中获取对象集合,使用类型,但强制子类来实现getFooBars()
方法。
我遇到的问题:
.Net不允许定义静态抽象方法,因此我无法创建public static abstract IEnumerable<FooBarizable> GetFooBars()
并强制实施子类来实现它。
实现的方式并不强制在子类中实现该方法,但我尝试至少抛出NotImplementedException
。问题是当我在管理器中调用MethodInfo method = type.GetMethod("GetFooBars");
时,如果子类化酶没有实现该方法,method
为空,而是调用NullPointerException
。
我试图创建一个实例方法而不是静态的静态方法,它解决了强制问题,因为子类必须实现它,但是我创建一个不必要的实例来调用它似乎不正确方法。
那么,是否有任何解决方案来强制子类实现getFooBar()
方法?如果没有,我怎样才能抛出NotImplementedException
而不是{{1 }}
答案 0 :(得分:4)
是否有任何解决方案来强制子类实现
getFooBar()
方法?
不适用于静态方法。静态方法与特定类相关联,因此它们不能被继承,也不能被抽象或虚拟。
如果要使方法具有多态性,则需要使用实例方法。
如何抛出
NotImplementedException
而不是NullPointerException
您获得该异常的结果是因为该类型没有 GetFooBars
方法,因此method
为null
。所以你可以首先检查null:
public void showFooBarizables(){
MethodInfo method = type.GetMethod("GetFooBars");
if(method == null)
throw new NotImplementedException();
IEnumerable<FooBarizable> FooBars = (IEnumerable<FooBarizable>)method.invoke(null, null);
show(FooBars);
}
但抛出该异常有点误导,因为调用者似乎没有实现showFooBarizables
方法,而不是基础GetFooBars
。
由于这些方法似乎是工厂方法,或许您需要为每种类型设置工厂?您似乎正在尝试使用泛型作为重载的替代品。工厂方法通常不是通用的,因为它们必须为每种类型具有不同的逻辑。您可以创建一个包含公共代码的“基础”工厂,然后为每种特定类型对 factory 进行子类化。
答案 1 :(得分:4)
当然.NET不允许你编写虚拟静态方法:)
虚拟方法的重点在于,当您在Base.DoSomething
类型的实例上调用Derived
方法时,它是Derived.DoSomething
中执行的代码。但这意味着你需要实例知道它的实际运行时类型,以便你知道应该执行什么方法。
典型的替代方案是使用某种形式的工厂界面。也就是说,您将获得相关实例类型的提供者的实例,而不是查询Foo.GetFooBars
或Bar.GetFooBars
。 Fooizer.GetFooBars
和Barizer.GetFooBars
,其中Fooizer
和Barizer
都实现了IFooBarProvider
。 GetFooBars
不适合FooBarizable
界面 - 因为它不属于它所在的位置。面向对象的设计,责任,替代原则以及所有这些:)
然后,如果您需要在代码中强制执行(例如,为了确保有人不忘记实现正确的提供程序),您可以在您的类型上创建一个抽象实例方法或属性:
public abstract class FooBarizable
{
protected abstract IFooBarProvider GetDefaultProvider();
}
根据您实际尝试的内容,将这些类设为通用可能是有意义的。或者不是:)
答案 2 :(得分:2)
您不能强制子类定义静态方法。如您所述,抽象方法不能是静态的,interfaces work with instances only。我认为你试图把太多的东西放到一个班级。看起来你想要创建一些法兰克工厂。而只是将工厂功能和抽象父对象分开。
public abstract class FooBarizable {
public string Name { get; set; }
}
工厂示例:
public static class FooBarizableFactory {
public static IEnumerable<FooBarizable> GetFooBars(Type type){
var parentType = typeof(FooBarizable);
if (!parentType.IsAssignableFrom(type))
throw new ArgumentException("Not a FooBarizable");
switch(type.Name) {
case "Foo":
return new List<Foo>() { new Foo () };
case "Bar":
return new List<Bar>() { new Bar() };
default:
throw new ArgumentException("Not a known FooBarizable");
}
}
}
用法:
var fooBars = FooBarizableFactory.GetFooBars(typeof(Foo));
Demo的想法。
答案 3 :(得分:1)
.Net不允许定义静态抽象方法
因为C#编译器使静态为抽象和密封。所以你不能把它简单化为抽象或密封。
问题是当我调用MethodInfo方法=时 type.GetMethod(&#34; GetFooBars&#34);在经理中,如果亚类酶没有 实现方法,方法为null,并且NullPointerExceptionis 而是打来电话。
我说静电是抽象的和密封的。因此,由于它的密封派生类不会有GetFooBars
方法。
您可以使用BindingFlags.FlattenHierarchy flag。这样它将检查基类的受保护和公共静态类。如果它没有在派生类上实现,它将检查基类。因此,如果派生的类没有这种方法,那么在你的stiuation基类中将调用GetFooBars
。
答案 4 :(得分:0)
无法通过任何形式的继承或多态来强制执行静态方法,但潜在的解决方法是为FooBarizable
实现扩展方法,以便任何继承它的类都可以访问扩展名。
答案 5 :(得分:0)
静态方法与类的对象(实例)无关,它始终与类本身相关。
强制执行方法的一种方法是使用接口。 另一种方式,这就是我认为你想要的,因为这种方法在不同的实例中会有不同的行为,会使用抽象方法。
public abstract class AbstractClass
{
public abstract int MustIMplementThis(string param1);
}
public class ChildClass : AbstractClass
{
public override int MustIMplementThis(string param1)
{
throw new NotImplementedException();
}
}
从AbstracClass继承的所有类都必须实现父类中列出的方法。