关于c#:为什么抽象类需要从它们实现的接口定义抽象方法?

Why do abstract classes need to define abstract methods from interfaces they implement?

当抽象类实现接口时,还需要定义或声明方法(如前所述):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public interface MyInterface
{
  void Method();
}

public abstract class MyAbstractClass : MyInterface
{
  public abstract void Method(); // required, even though MyAbstractClass does not implement
}

public class MyClass : MyAbstractClass
{
  public override void Method()
  {
  }
}

public interface MyInterface2 : MyInterface
{
  // no need to declare Method() -- why can't abstract classes do the same for unimplemented methods?
}

C语言需要定义实现接口的抽象类的抽象方法的设计原理是什么?抽象类需要定义一个它没有实现的方法,这似乎是完全多余的(更糟的是,对于实际实现该方法的类,必须将该方法标记为override)。我看不出为什么抽象类不能像MyInterface2那样工作,它继承自MyInterface,但不需要声明MyInterface的方法。


抽象类是完全成熟的类型,只是它不能实例化。因此,即使其某些方法没有实现,也必须声明其完整合同。特定抽象类的用户必须能够绑定到其所有方法,无论这些方法来自接口还是直接在抽象类中声明。接口中的方法没有(至少)在抽象类中声明(如果甚至没有实现),使用的方法无法绑定到它们。

此外,类和接口是松散耦合的。类可以声明一个方法,该方法随后映射到由其子代实现的接口中的同一签名方法。因此,从语言设计的角度来看,要求直接在抽象类上实现接口的所有方法,以便在抽象类中实际声明,这也是一个"好主意"。

您可以将接口视为可分离的特性(除非使用显式实现)。抽象类可以独立存在,它的直接用户不需要知道它的任何接口。

由于抽象类的整个概念在实践中需要充分利用虚拟方法的技术机制,因此只有虚拟方法才能在没有实现的情况下保留,这是一种设计特征。

更新:示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public interface IFoo { void M(); }

public abstract class Bar : IFoo
{
    public virtual abstract void M();

    public void N() { }
}

public class Baz : Bar
{
    public override void M() {}
}



public void Method(Bar par)
{
    par.M();
}



Baz x = new Baz();
Method(x);

Method见变量x表示为Bar—既不表示Baz,也不表示IFoo。换句话说,类Bar的用户不关心它是否实现了一个、两个、十个或根本没有接口。它所做的就是访问它的成员。它依赖于Bar的合同,而不是IFoo的合同。因此,如果Bar实施IFoo,则必须定义IFoo中的所有成员。


在实现接口的抽象类中创建的方法不需要是抽象的。抽象类也可以包含非抽象方法,您可以在那里定义接口的完整实现。继承类不需要重写这些方法中的任何一个。

此外,在msdn中对抽象类进行了描述:

An abstract class must provide implementation for all interface members.

An abstract class that implements an interface might map the interface methods onto abstract methods.

注意"可能"这个词,它不是"必须"。

请注意,msdn对实现接口的说明:

When a class or struct implements an interface, the class or struct must provide an implementation for all of the members that the interface defines.

对于各种类和结构都是如此。


用方法void Bar()实现IFoo的类可以选择是否公开一个公共方法Bar(),或者是否希望使用一个非公共成员来实现接口〔C〕要求直接实现方法是公共的还是私有的;vb.net还允许protected的作用域,其中对于抽象类来说,h通常是最有用的类型。

抽象类可以通过两种有用的方法实现IFoo.Bar()

1
2
3
4
5
6
public abtract void Bar();

// or

protected abstract void IFoo_Bar(); // Note that the exact name is arbitrary
void IFoo.Bar() { IFoo_Bar(); }

这两种实现都是合理的。第一种假设不合理,认为类希望有一个在其代码中不存在的公共方法;第二种假设要求编译器"猜测"应该为抽象方法指定什么名称。因为没有比任何选择更好的行为,C要求程序员指定所需的行为。