1/Путь к первому мобильному приложению. Часть 1.11 - Изучаем язык Dart: ООП. Интерфейсы и миксины (mixin)

Наследование в языке Dart ограничивает возможность класса наследоваться от нескольких других классов. Для этого необходимы интерфейсы. И в отличии от других языков программирования в Dart интерфейс это не отдельная сущность, а тот же класс, который может выступать классом объекта и реализовывать интерфейс для другого класса.

Для реализации интерфейса используется ключевое слово implements.

// Неявные интерфейсы
class Person {
  final _name;
  Person(this._name);
  String greet(String who) => 'Hello, $who. I am $_name.';
}
class Impostor implements Person {
  get _name => '';
  String greet(String who) => 'Hi $who. Do you know who I am?';
}
String greetBob(Person person) => person.greet('Bob');
// Программа
void main ( ) {
  print(greetBob(Person('Kathy'))); // Hello, Bob. I am Kathy.
  print(greetBob(Impostor())); // Hi Bob. Do you know who I am?
}

Наследование классов vs реализация интерфейсов

При наследовании производный класс не обязан определять те же поля и методы, которые есть в базовом классе (за исключением абстрактных методов). Если базовом классе определяется конструктор, то производный класс обязан определить свой конструктор, при котором вызывается конструктор базового класса. В производном классе мы можем обращаться к реализации базового класса с помощью ключевого слова super. Не поддерживается множественное наследование.

При реализации интерфейса производный класс должен определить все поля и методы, которые определены в классе интерфейса. Если в базовом есть конструктор, то производный класс НЕ обязан определять свой конструктор. В производном классе мы НЕ можем обращаться к методам реализованного интерфейса с помощью ключевого слова super. Поддерживается множественная реализация интерфейсов.

Для решения множественного наследования в Dart применяются ещё миксины (mixin).

По своей сути миксин это класс, который не содержит конструктор и задается с помощью ключевого слова mixin (но можно и class). Также при создании миксина мы можем ограничить через ключевое слово on в каких классах и его наследниках он может быть использован после ключевого слова with

// Миксины
mixin moreParams /*on mathLite*/ {
  int a = 1;
  int b = 2;
  void sum ( ) => print ( '${a+b}' );
}
class mathLite {
  int c = 10;
  void q ( ) => print ( '${c*c}' );
}
class mathFull extends mathLite with moreParams {
  int d = 15;
  void z ( ) => print ( '${d*d*d}' );
}
// Программа
void main ( ) {
  var m1 = mathLite ( );
  m1.q ( ); // 100
  var m2 = mathFull ( );
  m2.q ( ); // 100
  m2.z ( ); // 3375
  m2.sum ( ); // 3
}