Подтвердить что ты не робот

Почему можно создать экземпляр встроенного интерфейса Dart?

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


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

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

Если я попытаюсь использовать конструктор factory вместо этого, возвращая экземпляр реализации, я получаю ошибку времени компиляции (попробуйте):

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

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

Однако это, по-видимому, противоречит реальности, что List<E> 1 в Dart core library - это интерфейс 2 но он имеет несколько конструкторов и может быть инстанцирован, Например, это работает отлично (попробуйте):

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

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


1Dart: Библиотеки: corelib: interface List <E>
2 "Большая часть Dart Core Library определена в терминах интерфейсов". 3
3Dart: Tutorial: Интерфейсы

4b9b3361

Ответ 1

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

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

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

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

class ConcreteList implements List {
  ConcreteList() {}
}

Что это значит, он позволяет определять конструкторы в интерфейсе. Когда вы вызываете их, выполняя new List() (или независимо от вашего интерфейса), он знает, как создать экземпляр ConcreteList, потому что класс factory, который вы указали для этого интерфейса.

Это дает вам возможность полностью инкапсулировать конкретный тип за интерфейс, включая даже точку построения.

Конструктор factory выглядит следующим образом:

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 - конструктор (названный) factory. Конструкторы factory позволяют вам абстрактно создавать экземпляры. Вы вызываете их как обычный конструктор, но они автоматически не генерируют новый экземпляр объекта. Вместо этого вы можете делать все, что захотите, в теле конструктора. Здесь каждый раз, когда вы делаете:

new Point.zero();

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

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