当使用接口的飞镖?(When to use interfaces in Dart?)

2019-07-29 07:42发布

我读飞镖的文档,我是有点糊涂了,也许是因为我来自红宝石来了,至于如何使用接口。 当然,接口是不是唯一的DART和有关于何时应该使用的接口相当数量的解释在那里的。 这其中 ,例如,似乎是说,当你在一个团队是接口仅仅是有用的。 它是什么,甚至应该在开源的世界里,每个人都读取和重用别人的代码是什么意思?

我已经看到了一个有趣的解释似乎暗示接口用于:

  1. 在缺乏多重继承的语言,
  2. 对于这个问题,他们在某种程度上充当了没有多重继承的解决办法。

我不明白这一点。 据我所知,在Ruby中模块是一个解决方法,因为他们让我来定义与实际的身体真正的方法。 接口只允许我定义一个类实现它应该有什么样的方法。 有什么收获? 谁能告诉一个真正有用的例子,在那里我可以立即看到使用接口的价值?

PS与此相关的,是有办法使用多重继承的飞镖的方法吗?

Answer 1:

更新: interface关键字已经被从DART删除 。


因为它们允许你切换类的实现,同时仍然允许该类型在传递验证符合接口的要求,接口是有用的。

采取以下(通常使用)例如:

interface Quackable {
  void quack();
}

这定义了将被传递到如一个方法的类的要求:

sayQuack(Quackable quackable) {
   quackable.quack();
}

这使您可以使用一个Quackable对象,如任何实现的:

class MockDuck implements Quackable {
  void quack() => print("quack");
}

class EnterpriseDuck implements Quackable {
  void quack() {
    // connect to three enterprise "ponds"
    // and eat some server bread
    // and say "quack" using an messaging system
  }

}

这两种实现的将与sayQuack()函数工作,但一个需要比其他基础设施显著少。

sayQuack(new EnterpriseDuck());
sayQuack(new MockDuck());

我使用这个模式所有的时间在Java世界,构建解决方案,利用一些“企业鸭”的时候。 当本地开发,所有我只需要的是能够调用sayQuack()函数,并返回硬编码,模拟数据。

鸭打字

由于DART可选类型,你实际上并不需要使用界面,只需编写一个包含正确的方法签名就可以了(尽管这些工具将无法对其进行验证)一类。

class Person {   // note: no implements keyword
  void quack() => "I'm not a duck";
}

sayQuack(new Person()); // provides the quack method, so this will still work

所有的类都是接口

最后,所有的类都还接口。 这意味着,即使第三方系统可能已不使用接口编写,你仍然可以用一个具体的类,就好像是一个接口。

例如,假设下面的企业库:

class EnterpriseDuck { // note: no implements keyword
  void quack() {
    // snip
  }
}

sayQuack(EnterpriseDuck duck) {  // takes an instance of the EnterpriseDuck class
  duck.quack();
}

而你要一个模拟鸭进入该类型检查可以验证的方式sayQuack方法。 您可以创建mockDuck只需通过使用EnterpriseDuck作为接口来实现由EnterpriseDuck,隐含的界面:

class MockDuck implements EnterpriseDuck {
  void quack() => "I'm a mock enterprise duck";
}

多重继承

在多重继承而言,这是不可能的飞镖。 你可以,但是,实现多个接口,并提供自己所需要的方法,例如实现:

class MultiDuck implements Quackable, EnterpriseDuck, Swimable {
  // snip...
}

接口可以有默认类

当您使用飞镖,你会发现,大多数“类”实际上是接口。 列表,字符串等..与默认的实现提供的所有接口。 你打电话的时候

List myList = new List();

你实际上是使用List接口,而新的关键字从界面到基础的默认列表实现重定向。

至于在团队发展

接口是在团队开发有用的,即使在开源世界。 该接口定义,你应该建设,使您的组件与我的组件工作的方法和属性。 你可以建立自己的测试实现该接口的,我可以建立我的具体实现该接口的,当我们都做了,我们可以整合。 如果没有出版,共享接口,我需要提供我的具体实现,你可以真正开始之前。

希望帮助!



Answer 2:

基本上,接口无关多重继承。 这样做时,它是可能的假多重继承和滥用接口,但如果你想真正的多重继承(或混入或性状),然后飞镖不提供他们(目前 - 我相信,混入会找到自己的方式在某一天)。

什么是接口好的是明确的合同 。 你说你有两个组成AB需要相互合作。 你肯定可以拨打BA直接,它会工作,但下一次你会想改变B ,你将不得不寻找A它是如何使用它。 这是因为B没有暴露的显式接口 。 是的,界面右边的字不实现 ,但暴露

如果隐藏的落实B的接口后,只提供了接口A ,那么你可以改变B随意,只担心仍然露出相同的接口 。 接口甚至可以由多个类暴露,调用者不必关心(甚至不知道)。

需要注意的是这个词接口有这里有两个含义:组件的总承包合同 ,这也可以在纯英文的文档中描述,和一个特殊的语言结构 ,可以帮助你描述的(并且也执行)合同的某些部分直接在编程语言。

你不一定必须使用的语言结构,但它被认为是良好的作风,以用它来形容合同的编程语言,可以让你的那些部分。

现在,到底是什么合同吗? 简单地说,合同是什么样的分量从它的用户所期望的操作和用户可以从部件期望的说明。

举例来说,假设我有一个计算数字的绝对值的方法:

class MathUtils {
  /// Computes absolute value of given [number], which must be a [num].
  /// Return value is also a [num], which is never negative.
  absoluteValue(number) {
    ... here's the implementation ...
  }
}

这里的合同在文档注释(当然,不完全,我们也可以形容绝对值是什么,但是这是不够好)完全描述。 嗯......但评论的某些部分可以直接在语言表达的,对不对?

class MathUtils {
  /// Computes absolute value of given [number].
  /// Return value is never negative.
  num absoluteValue(num number) {
    ... here's the implementation ...
  }
}

需要注意的是合同的某些部分根本无法在编程语言来表达-在这里,语言没有想法,这需要留在评论什么绝对值 。 此外,你无法表达,返回值从不为负,所以这留在评论太多。 但实际上,你的代码的读者都知道的绝对值是什么(它从不为负),方法名是约的目的很清楚,这样的评论可以完全排除在外:

class MathUtils {
  num absoluteValue(num number) {
    ... here's the implementation ...
  }
}

所以,现在,合同的某些部分明确表示,使用语言的手段,有的部分隐晦地表达(你依靠的人知道什么是绝对值)。

而在语言接口用于解耦合同执行 。 这可能是矫枉过正的小程序使用,但它做更大的程序(不必需要团队合作),当不负有心人。

UFF,这竟然是比我预期的要长。 希望帮助。



Answer 3:

接口是类型系统的一部分,飞镖和类型声明是可选的。 这意味着,接口是可选的为好。

接口帮助您记录了你的对象响应的方法。 如果您实现接口,那么你承诺实现该接口的所有方法。

DART使用该信息来呈现类型不匹配的编译时间警告,提供更多有益的建议了代码辅助,并帮助一些重构。



文章来源: When to use interfaces in Dart?