我们可以用具有扩展方法的接口代替抽象类吗?

本文关键字:接口 抽象类 方法 扩展 我们 | 更新日期: 2023-09-27 18:01:39

我们即将从头开始一个项目。根据设计讨论,我想提出这个话题。

大多数时候,我看到抽象类被用来为一些具体的方法提供一些默认的/通用的行为。

所以,我想定义那些具体的方法作为我将要开发的接口的扩展方法来代替抽象类。

关于我的设计决定,有人能指导我吗?如果你不同意我的观点,请用我们可能面临的情况/问题来证明你的论点。所以,它会提高我的知识。

我们可以用具有扩展方法的接口代替抽象类吗?

这两种方法非常不同。

使用抽象类和抽象/虚拟方法,您允许派生类覆盖扩展方法所不具备的行为。扩展方法终究是扩展,它们不是类型的一部分,当有人检查API和类型提供的特性时,很难发现它们。

第二点,为您自己创建的类型创建扩展方法在我看来不是那么合乎逻辑。使用一个抽象基类可以保持层次结构的清晰,并且可以让你的模型对被覆盖的行为进行修改。

在c#中引入扩展方法是因为一个非常特殊的需求。

当他们设计LINQ时,他们意识到他们不想创建一个包含所有已知LINQ方法(如WhereSelect)的新接口,因为这意味着任何枚举或集合实现都需要实现它。

上面提到的事实有一个重要的缺点:它需要从基类库大量更改类的源代码,并且任何第三方库或实现自定义集合的项目根本无法利用LINQ。

然后他们想到了一种可以直接与迭代器(即IEnumerator<T>)一起工作的方法,并且可以与任何IEnumerable<T>兼容,而无需修改任何现有代码,而只需向新的汇编成员添加新代码。

他们还发明了扩展方法,它们的实现方式类似于静态方法,它们将充当给定类型的实例成员

自从扩展方法开始以来,它们已经在许多其他场景中实现,但它们总是覆盖这两个用例:

  1. 我有一个很大的代码库,我想为所有类型的派生(类)或实现(接口)提供一个功能,而不必修改它们,实现一个跨大量代码的新接口(增加引入新错误的机会)。

  2. 我没有一些项目的源代码,我想扩展一些类型来支持一些新的方法。

超出这些用例的任何内容都是对扩展方法的滥用。

扩展方法不能替代常规的基于类的面向对象编程。

基本上你可以扩展每一个类或接口——Linq-extension方法没有做任何其他的事情。

尽管你可以直接在接口中定义这些方法,但你总是需要一个包含这些扩展的静态公共类。

回答你的问题,我怀疑在扩展方法中定义默认行为是一件好事,因为它完全损害了该接口的实际意图。当创建扩展方法时,该(扩展)类/接口的所有实例共享这些方法,因此您所做的是说我的接口的每个实例都可以被视为我的抽象类。

说到这里,您应该区分行为(接口)和实际处理(类)。混合两者最终会使你的设计变得相当复杂。

下一个是通过定义扩展方法完全绕过继承。那么,如果您想要重写默认行为该怎么办呢?将它们定义为new或任何其他奇怪的变通方法将会丢失,因为您的设计根本不允许继承。

从我的观点来看,最后一点是你应该对你无法控制的类使用扩展方法。但是,当您可以修改代码时,您可能不会使用它们。