C# - 接口澄清

3

我了解到一些关于接口的知识:

" 接口是类必须遵守的契约定义。它不会继承任何东西。 "

在定义接口和抽象类之间的区别时,我可以这样说吗:

当一个类派生自抽象类时,它被称为真正的继承。当一个类使用接口时,它不是继承,而是实现契约。

7个回答

3

是的,你说得对。接口只是类的一种约定。

注意:接口不继承任何派生于System.Object类型的类型。接口只是一个抽象类型,由一组虚方法组成,每个虚方法都有自己的名称、参数和返回类型。接口方法不能包含任何实现;因此,接口类型是不完整的(抽象的)。

例如:

interface I1
{
}
interface I2
{
}

abstract class a1
{
}
abstract class a2
{

}
class App:a1,I1,I2  //no Error
{   
static void Main(string[] args)
{       
}
}

注意:CLR只允许类型从一个其他类型继承,该类型的根基类型为System.Object

       interface I1
        {
        }
        interface I2
        {
        }

        abstract class a1
        {
        }
        abstract class a2
        {

        }
        class App:a1,a2,I1,I2  //  Error
        {   
        static void Main(string[] args)
        {       
        }
        }

2

是的,你说得对,简单来说:

什么是抽象类?

抽象类是一种特殊的类,不能被实例化。那么问题来了,为什么我们需要一个不能被实例化的类呢?抽象类只能被子类(派生类)继承,也就是说,它允许其他类从它那里继承,但不能被实例化。这样做的好处在于,它强制所有的子类都遵循同样的层次结构或标准。换句话说,它是一种强制性的契约,要求所有的子类遵循同样的层次结构或标准。

什么是接口?

接口不是一个类,而是由单词“interface”定义的实体。接口没有实现,只有方法的签名或者说,方法的定义而没有具体实现。与抽象类的相似之处在于,它是用于为所有子类定义层次结构或特定方法集及其参数的契约。它们之间的主要区别在于,一个类可以实现多个接口,但只能继承一个抽象类。由于 C# 不支持多重继承,因此使用接口来实现多重继承。

二者的结合

当我们创建一个接口时,我们实际上创建了一组没有任何实现的方法,这些方法必须被实现的类覆盖。优点在于,它提供了一种让一个类成为两个类的一部分的方法:一个来自继承层次结构,一个来自接口。

当我们创建一个抽象类时,我们创建了一个基类,其中可能有一个或多个已完成的方法,但至少有一个或多个方法未完成而被声明为抽象的。如果一个抽象类的所有方法都是未完成的,则与接口相同。抽象类的目的是为派生类定义如何工作的基类定义,然后允许程序员在派生类中填写实现。


1
当一个类使用接口时,这不是继承,而是契约的实现。
是的,那正是它的工作方式。
如果您研究一个接口继承另一个接口时发生的情况,可能会更清晰一些。这可能很困惑,因为我们刚刚说过使用接口时不涉及继承,只是一个契约定义。如果您查看以下代码:
interface IA
{
    void MethodA();
}

interface IB : IA
{
    void MethodB();
}

class B : IB
{
    public void MethodA() { }
    public void MethodB() { }

}

class AB : IA, IB
{
    public void MethodA() { }
    public void MethodB() { }
}

如果您检查类 BAB 的 IL 代码(使用 ildasm 或类似工具),您会发现这两个类在实现的接口方面是相同的。接口 IB 作为一种“快捷方式”,包括了接口 IA,但传统意义上的继承并没有涉及到。

1
当一个类从抽象类派生时,它被称为真正的继承。当一个类使用接口时,它不是继承,而是对约定的实现。
  • 是的

1
抽象类和接口的区别在于,接口不定义任何方法的实现,而抽象类提供了一些实现。这是唯一的区别。抽象类和具体类的区别在于,抽象类至少有一个成员没有提供实现。
接口可以派生自其他接口。
多重继承仅允许用于接口,原因很复杂,是先前时代宗教战争的一部分。

1
实际上,从技术角度来看,一个抽象类并不需要包含至少一个不包含实现的成员。一个抽象类可以定义所有带有实现的方法,并将它们标记为虚拟的。区别在于,接口永远不可能提供实现,因此指定了实现类必须遵守的契约。 - Mike Hofer
很好,但如果一个基类包含抽象方法,则还会定义契约。 如果抽象类没有抽象方法,则该指示是多余的。 鉴于我在这个主题上提倡“实用主义者”的观点,即使它不是抽象的,我也会接受将标记为抽象的类称为抽象的。 在语义上适当的参考框架中,界面实现不能称为“继承”,我认为将没有抽象方法的类称为抽象类也是不正确的。FYI,我完全支持明确定义契约。 - Paul Keister

1

抽象类和接口的区别最好通过研究这两个关键字的使用来理解:

本质上,接口是一种特殊的构造,它定义了一个代码契约。当你创建它时,它可以不包含任何实现;它只是指定了合同所需的属性和方法的签名。当一个类实现接口时,它必须按照合同中指定的每个属性和方法提供完全相同的实现。提供实现的责任在于实现类。

一个抽象类可以自由地提供所需的实现,也可以不提供。它本身可以实现一个接口。抽象类只需要被标记为“abstract”。派生类可以通过在抽象(基)类中将方法标记为“virtual”,并在派生类中使用“overrides”关键字来重写其成员。但是,抽象基类没有义务提供任何功能;也没有义务提供缺少实现的最小数量的虚拟方法。
希望这有所帮助!

0

接口定义了一个接口。只需想想“接口”这个词。

简单明了。

它定义了您如何与类进行交互(接口!)。

只需将大脑重新引回自身,您就会发现答案就在您面前。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接