.NET 继承:从 MusiInherit/abstract 函数返回实现给定接口的类的实例
我有一个包含抽象/MustInherit 方法的基类。我希望此方法返回实现给定接口的类的实例。
当我在派生类中实现该方法时,出现编译器错误,因为返回类型不匹配(即,在抽象类中,返回类型是接口的类型,而在派生类中,返回类型是实现接口的类)。
谁能为我澄清根本问题吗?我不太明白出了什么问题。特别是抽象方法指定的返回类型是一个接口,它不能被实例化,那么方法的实现一定要返回一个实现该接口的类的实例吗?也许我只是只见树木不见森林。
我可以通过使基类通用(并且我可以指定 T 必须实现我的接口)来解决这个问题,然后抽象方法将返回 T 的实例。但我不确定该解决方案。这似乎有点黑客,我不明白为什么我不能用直接继承来做到这一点。
I have a base class which contains an abstract/MustInherit method. I want this method to return an instance of a class which implements a given interface.
When I come to implement the method in the derived class, I get a compiler error because the return types do not match (ie. in the abstract class, the return type is that of the interface, whereas in the derived class the return type is the class which implements the interface).
Can anyone clarify the underlying problem for me? I can't quite get my head around what's wrong. Especially given that the specified return type of the abstract method is an interface, which can't be instantiated, so surely the method implementation must return an instance of class which implements the interface? Maybe I just can't see the wood for the trees.
I can code around the issue by making the base class generic (and I can specify that T must implement my interface), then the abstract method would return an instance of T. I'm not sure about that solution though. It seems a bit of a hack, I don't get why I can't do it with straight inheritance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我现在设想的代码方式是,您有一个抽象基类,其中包含一个方法 (
GetFruit
),该方法返回一个我将称为IFruit
的接口。在派生类中,您希望能够(从同一个GetFruit
方法)返回实现IFruit
接口的Apple
对象。然而,尽管这可能很方便,公共语言规范 (CLS) 不允许兼容语言支持返回类型协方差。这包括所有 .NET 语言,例如 VB.NET 和 C#。关于出现此限制的确切原因以及到底是什么造成了此限制,存在很多错误信息,但简单的答案是,您无法将派生类中方法的返回类型缩小为更具体的派生。
这意味着,即使
Apple
实现了IFruit
,您也无法在派生类中键入该方法来返回Apple
。重写的方法必须具有与其基类相同的返回值签名。 因此,对于从基类派生的所有类,每个方法都必须返回相同类型的对象 (IFruit
)。只需更改派生类中方法的返回值与基类中方法的类型相同将解决您的问题。您提到了使基类通用的可能性,虽然这可能会起作用,但它似乎引入了不必要的复杂性。使用我上面设计的示例,由于
Apple
完全实现了IFruit
接口,因此您应该通过简单地返回IFruit
来获得类型检查甚至智能感知的全部好处。 code> 来自派生类。编辑:如果您愿意接受一些有点黑客的东西,您可以随时在派生类中重新声明该方法(通过将其标记为
new
或<代码>阴影)。这将允许您返回所需的任何类型的对象,而不管基类中方法的签名如何。但是,请记住,无法同时重新声明和重写方法,因此您并不是真正的多态。The way I envision your code now is that you have an abstract base class containing a method (
GetFruit
) that returns an interface that I'll callIFruit
. In a derived class, you want to be able to return (from this sameGetFruit
method) anApple
object that implements theIFruit
interface.However, as convenient as that might be, the Common Language Specification (CLS) does not allow compliant languages to support return type covariance. This includes all of the .NET languages, like VB.NET and C#. There is a lot of misinformation that exists on exactly why this limitation arises and what exactly is responsible for this limitation, but the simple answer is that you cannot narrow the return type on a method in a derived class to a more specific derivation.
That means that even though
Apple
implementsIFruit
, you cannot type the method in a derived class to returnApple
. The overridden methods must have the same return value signature as that of their base. So, instead, each method must return an object of the same type (IFruit
) for all classes that derive from your base class. Simply changing the return value of the method in your derived class to be the same type as the method in the base class will solve your problem.You mention the possibility of making the base class generic, and while this would probably work, it seems to introduce unnecessary complexity. Using my contrived example above, since an
Apple
fully implements theIFruit
interface, you should get the full benefit of type checking and even Intellisense by simply returningIFruit
from your derived classes.EDIT: If you're open to something a little bit hack-ish, you can always re-declare the method in your derived class (by marking it as
new
orShadows
). This will allow you to return whatever type of object that you want, regardless of the signature of the method in the base class. However, remember that there is no way to re-declare and override a method at the same time, so you're not truly polymorphic.这是您可以完成您所追求的任务的一种方法:
问题是重写的方法被限制为与其基础方法具有完全相同的签名。假设您要创建一个实现
ISomething
的值类型,然后在 Derived 中专门进行重写以返回该值类型。现在,重写的方法返回一个实现接口的值类型,但是,从 Base 调用该方法时,您会期望获得接口形式的装箱值类型。如果派生调用在通过 Base 调用时返回未装箱的值,则调用代码将尝试访问它,就像它已装箱一样,从而导致失败。Here is one way you could accomplish what you're after:
The issue is that overridden methods are constrained to have the exact same signature as their base. Suppose you were to create a value type that implements
ISomething
and then specialized the override in Derived to return the value type. Now the overridden method is returning a value type that implements the interface, but, calling the method from the Base, you would expect to get a boxed value type of the form of the interface. If the Derived call returned an unboxed value when calling through the Base, the calling code would try to access it as if it were already boxed, causing a failure.从你的问题来看,你似乎有这样的事情:
解决方案是保留基类的返回类型,即:
From your question it seems like you have something like this:
The solution is to keep the return type from the base class i.e:
只需将派生类中的方法的返回类型设置为接口即可。
例子:
Just make your method's return type in the derived class the interface.
Example:
您无法更改派生类中重载方法的返回类型。无论是在 C#、C++ 还是 VB.NET 中。保持原样,您可以返回实现该接口的类的实例。
原因是:抽象方法旨在用于仅在不同派生类的公共接口上工作的抽象算法。你所描述的只是抽象工厂的情况。您可以在这里找到详细的解释:
http://en.wikipedia.org/wiki/Abstract_factory_pattern
You cannot change the return type of an overloaded method in a derived class. Neither in C#, nor in C++, nor in VB.NET. Leave it as it is, and you can return an instance of class which implements the interface.
The reason: abstract methods are intended to be used in abstract algorithms that work only on the common interface of different derived classes. What you have described is just the case of an abstract factory. You will find a detailed explanation here:
http://en.wikipedia.org/wiki/Abstract_factory_pattern