这是一个关于C#基础知识的哲学问题:我想知道完全抽象的类可以模拟接口的接近程度。假设我们有以下界面:
public interface INativeInterface
{
void PerformAction();
String Property { get; set; }
}
以及抽象类:
public abstract class ISimulatedInterface
{
public abstract void PerformAction();
public abstract String Property { get; set; }
}
他们有很多共同点,不是吗?我所知道的差异是:
使用反射或类似的东西可以跳过这些限制吗?
我意识到接口和抽象类在root中是不同的:接口声明“可以表现得像”的条件,抽象类 - “是一种”,但即使这似乎是如此接近,以至于必须讨论这些实体之间的低水平差异。这个问题甚至可以听起来像“你会用C ++创建一个接口”。
答案 0 :(得分:4)
使用反射或类似的东西可以跳过这些限制吗?
没有。公共语言运行时级别的抽象类和接口是不同的概念。因此,它在C#中是不可能的,因为最终受限于CLR的边界。
我想知道完全抽象的类可以模拟接口的接近程度。
这是可行的,但需要来自底层执行环境(无论是物理的还是托管的)的支持(或“允许”)。
过去我设计了一种完全取代接口抽象类的语言。是的,它确实支持这种“接口”的多重继承。但是,实施的特点可能不值得付出努力。主要的“低级别差异”是继承的抽象类的内部嵌入式实例必须保留在实现类的实例中,并且必须保持一系列this
指针。不用说,这是一种快乐的经历: - )
答案 1 :(得分:2)
所以,如果我理解你的问题,你有两个相关的问题。
第一个是“抽象类和接口之间有什么区别”;第二个是,“在C#中,我可以通过使一个没有具体方法的抽象类表现得像一个接口来绕过差异吗?”。
第一个问题在@Todd Schiller的链接中得到了很好的回答。
第二个问题更复杂。
您可能可以创建构建时任务,将所有抽象类转换为接口而无需具体实现。我从来没有尝试过 - 因为我认为这样做没有任何好处,还有很多很多缺点。
最大的缺点是您的代码变得更难以调试和维护。开发人员学习何时创建抽象类,何时创建接口;这是一个既定的,普遍认同的成语。在你的代码库上工作的新开发人员将需要学习很多新东西 - 并且引入一种思考接口和抽象类的新方法将使这个过程变得更难和更长。
在调试应用程序时,在源代码中看到抽象类的开发人员 - 但在运行时代码中看到它实际上是一个接口 - 可能会感到困惑,并花时间试图弄清楚为什么会发生这种情况而不是追查真正的错误。
据我所知,没有明显的好处。
答案 2 :(得分:1)
对我来说,这真的归结为他们的能力。接口永远不会为其任何操作提供实现;它只承诺任何使用它的人都必须提供一些东西。抽象类可以为其任何操作提供实现,这些操作可以由其子类自行决定覆盖。不,你永远不可能通过反思覆盖这些限制,因为它们是语言本身的核心。
就使用抽象类代替接口而言,它再次归结为您需要完成的任务。如果需要提供一些基本实现,则必须使用抽象类 - 否则,请使用接口。
您已经提到的其他一些差异。您可以在C#中实现多个接口,但是您只能从单个类派生(抽象或其他)。
答案 3 :(得分:1)
它可能是OOPS哲学背景下的热门话题。我们知道它几乎没有技术差异,如接口没有构造函数,继承类必须实现所有方法等但我喜欢用真实的方法来讨论它世界情景。实际上我认为接口是一个对象与其消费者之间的契约。但是抽象类不是契约,即使两者都可以用来实现“liskov替换原则”。我想列出现实生活中的两种情况..
1。)想象一个绘图应用程序,它可能包含形状,矩形,正方形等。这里的形状可以是抽象类或接口类型。但是如果我需要确保我的应用程序中的每个对象在实例化时都必须具有状态。我无法通过接口实现此功能,因此接口无法保持对象的状态。
2.。)如果我的形状共享共同的值(静态值),我无法使用接口实现,所以我认为抽象类可以保持状态和行为
但考虑到界面这是一个关于行为的协议,看起来是一个真实的例子,动物和鸟类,这两个对象都有一些相似的行为,但我们不能说它们有共同的属性,鸟类和动物都可以走路,哭泣,吃,这些行动的执行完全不同。在我们的编程接口中,在您只需要协议而不需要任何状态的情况下,它是理想的候选者。好消息是消费者对象可以取代满足该协议的任何其他对象,D I是一个最好的例子。