12

注意:此问题已过时;interface声明语法已从 Dart 中删除:


据我所知,在Dart中实例化接口是不可能的。如果我只是尝试构造 a new MyInterface(),无论是否定义了构造函数,我都会收到运行时错误(尝试一下):

NoSuchMethodException - receiver: '' function name: 'MyInterface$$Factory' arguments: []]
interface MyInterface {}      
interface MyInterface {
  MyInterface();
}

如果我尝试使用工厂构造函数,返回一个实现的实例,我会得到一个编译时错误(试试看):

SyntaxError: factory members are not allowed in interfaces
class MyImplementation implements MyInterface {
  MyImplementation();
 }

interface MyInterface {
  factory MyInterface() { return new MyImplementation(); }
}

List<E>然而,这似乎与 Dart 核心库中的1是一个接口2的现实相矛盾,但它有多个构造函数并且可以实例化。例如,这很好用(试试看):

main() {
  var list = new List();
  list.add(5);
  print(list.last());
}

为什么可以List和许多其他内置接口实例化?是否有一些我错过的方法,或者他们只是作为内置类型接受特殊处理?


1 Dart: Libraries: corelib: interface List<E>
2 “Dart 核心库的大部分内容是根据接口定义的。” 3
3 Dart:教程:接口

4

2 回答 2

9

定义接口的语法是:

interfaceDefinition:
    interface identifier typeParameters? superinterfaces? factorySpecification? `{' (interfaceMemberDefinition)* `}'

请注意,factorySpecification必须在接口主体之前而不是在它内部。

所以这就是你写它的方式:

interface MyInterface default MyImplementation {

}

class MyImplementation implements MyInterface {
  MyImplementation();
}

或者,如果您想获得完整的通用定义:

interface MyInterface<E> default MyImplementation<E> {
    MyInterface(x);
}

class MyImplementation<E> implements MyInterface<E> {
  MyImplementation(this.x);
  E x;
}

编辑:对于更完整的示例,您可以阅读https://code.google.com/p/dart/source/browse/branches/bleeding_edge/dart/corelib/src/list.dartinterface List<E> 的源代码和相关来源位于https://code.google.com/p/dart/source/browse/branches/bleeding_edge/dart/runtime/lib/array.dartclass ListFactory<T>

于 2011-10-11T08:27:48.873 回答
2

Dartfactory用于两种不同的东西:工厂和工厂构造函数。工厂类如下所示:

interface List default ConcreteList {
  List();
  ...
}

class ConcreteList implements List {
  ConcreteList() {}
}

它的作用是让您在接口中定义构造函数。当您通过执行new List()(或您的接口是什么)调用它们时,它知道实际实例化ConcreteList,因为那是您为该接口指定的工厂类。

这为您提供了一种将具体类型完全封装在接口后面的方法,甚至包括构造点。

工厂构造函数如下所示:

class Point {
  static _zero;
  int x, y;

  Point(this.x, this.y) {}

  factory Point.zero() {
    if (_zero == null) _zero = new Point(0, 0);
    return _zero;
  }
}

这里,Point.zero是一个(命名的)工厂构造函数。工厂构造函数让你抽象实例化。您可以像常规构造函数一样调用它们,但它们不会自动生成对象的新实例。相反,您可以在构造函数的主体中自由地做任何您想做的事情。在这里,每次你这样做:

new Point.zero();

即使您每次都在使用,您也会得到相同的缓存对象,因为它们的工厂构造函数总是返回相同的对象。它们有几个用途:_zeronew

  1. 返回以前缓存的对象,就像我们在这里做的那样。
  2. 返回一个子类。这有点像接口的工厂类。您可能有一个可以使用的类,new但在某些情况下,您实际上可能希望返回它的子类以专门化其行为。工厂构造函数让您无需更改调用点即可做到这一点。
于 2011-10-20T14:29:17.343 回答