与默认方法和抽象类的接口,以及动机是什么?

时间:2017-10-03 07:54:34

标签: java c#

上下文

我最近遇到过这个C#提案default interface methods 我已经阅读了规范和更重要的是动机。可能我错过了什么,但动机有点让我感到恶心。

接口和完全抽象类之间唯一的实际区别是未来类可以实现(所以是[IS A])多个接口,但可以继承(所以是[IS A])来自一个抽象类,(以及所有后果)

我不清楚抽象类和接口与默认方法现在 除了 之间的确切区别是什么我们可以使用默认方法将多个(实现)继承带入图片,这对于抽象类是不可能的。 (我不想打开问题/讨论是好还是坏,这不是这里的主题)

然而,动机谈论完全不同,有三点:

  • " ... API作者在未来版本中将方法添加到界面而不破坏源..." 。那么一个" API"作者可以在未来的版本中添加方法,如果他实现了,而不会破坏任何内容。
  • " ...使C#能够与面向Android(Java)和iOS(Swift)的API互操作,..." 。我认为是一种语言设计决策,特别是关于抽象和OOP模式(如多重继承)比Swift更高级别。我也认为,这只是互操作问题的0.0%,也可以通过其他方式解决。
  • " ...事实证明,添加默认界面实现提供了" traits"语言功能..." 。这是一个非常浅薄的陈述,特别是它指的是维基百科" traits"。根据定义,traits允许添加没有多重继承的方法(与super具有[IS A]关系)。然而,接口肯定是关于[IS A] ......不是说这个事实,特征至少是可论证的良好实践

问题

我的问题是真正的差异(或动机)是什么,或者我缺少什么?

2 个答案:

答案 0 :(得分:1)

他们在Java 8中添加了此功能。因此,您可以添加Java标记,并向Java开发人员询问他们可以使用它做什么。它显然也存在HaskellScala

多继承

首先我想到的是多重继承。由于类可以实现多个接口,因此您可以例如解决diamond problem

在Java中,他们就是这样做的:

public interface InterfaceA {
    public default void foo() {
        System.out.println("A -> foo()");
    }
}

public interface InterfaceB {
    public default void foo() {
        System.out.println("B -> foo()");
    }
}

private class Test implements InterfaceA, InterfaceB {
    // Compilation error : "class Test inherits unrelated defaults for foo() from types InterfaceA and InterfaceB"
}

所以你必须实现方法(覆盖默认实现)或调用其中一个super

public class Test implements InterfaceA, InterfaceB {
     public void foo() {
        InterfaceB.super.foo();
    }
}

答案 1 :(得分:0)

在引入Default Method之后,似乎接口和抽象类是相同的。但是,它们在Java 8中仍然是不同的概念。

抽象类可以定义构造函数。它们更加结构化,并且可以具有与之关联的状态。相比之下,默认方法只能在调用其他接口方法方面实现,而无需参考特定实现的状态。因此,两者都有不同的用途,并且两者之间的选择实际上取决于场景的上下文。