Почему встроенный интерфейс List в Dart может быть создан? - PullRequest
12 голосов
/ 11 октября 2011

Примечание: Этот вопрос устарел; синтаксис объявления interface был удален из Dart:


Насколько я могу судить, невозможно создать интерфейс в Dart . Если я просто пытаюсь создать new MyInterface() с определенным конструктором или без него, я получаю ошибку во время выполнения ( try it ):

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> 1 в базовой библиотеке Dart - это интерфейс 2 , но он имеет несколько конструкторов и может быть создан. Например, это прекрасно работает ( попробуйте ):

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

Почему можно создавать экземпляры List и многих других встроенных интерфейсов? Есть какой-то метод, который я пропустил или они просто получают специальное лечение как встроенные типы?


1 Дарт: Библиотеки: corelib: Список интерфейсов
2"Большая часть базовой библиотеки Dart определена в терминах интерфейсов." 3
3 Дарт: Учебное пособие: Интерфейсы

Ответы [ 2 ]

9 голосов
/ 11 октября 2011

Синтаксис для определения интерфейса:

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;
}

Редактировать : для более полного примера вы можете прочитатьисходный код interface List<E> в https://code.google.com/p/dart/source/browse/branches/bleeding_edge/dart/corelib/src/list.dart и связанный источник class ListFactory<T> в https://code.google.com/p/dart/source/browse/branches/bleeding_edge/dart/runtime/lib/array.dart

2 голосов
/ 20 октября 2011

Дарт использует factory для двух разных вещей: фабрика классы и фабрика конструкторы .Класс фабрики выглядит следующим образом:

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();

Вы получите тот же кэшированный _zero объект, даже если вы используете new каждый раз, потому что конструктор фабрики всегда возвращаеттот самый.У них есть пара применений:

  1. Возврат ранее кэшированных объектов, как мы делаем здесь.
  2. Возврат подкласса.Это что-то вроде фабричного класса для интерфейса.У вас может быть класс, который вы можете new, но при определенных обстоятельствах вы можете захотеть вернуть его подкласс, чтобы специализировать его поведение.Конструкторы фабрики позволяют вам делать это без необходимости изменения места вызова.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...