🎴

Dart3でinterfaceを使う

2024/01/11に公開

interfaceとは?

https://dart.dev/language/class-modifiers#interface

インターフェースを定義するには、interface修飾子を使う。そのインターフェイスを定義しているライブラリ以外のライブラリは、そのインターフェイスを実装することはできるが、拡張することはできない。これは保証される:

クラスのインスタンス・メソッドの1つがこれに関する別のインスタンス・メソッドを呼び出すとき、常に同じライブラリのメソッドの既知の実装が呼び出されます。
他のライブラリは、インターフェイスクラスのメソッドが後で予期しない方法で呼び出す可能性のあるメソッドをオーバーライドすることはできません。これにより、もろい基底クラスの問題が軽減されます。

// Library a.dart
interface class Vehicle {
  void moveForward(int meters) {
    // ...
  }
}
// Library b.dart
import 'a.dart';

// Can be constructed
Vehicle myVehicle = Vehicle();

// ERROR: Cannot be inherited
class Car extends Vehicle {
  int passengers = 4;
  // ...
}

// Can be implemented
class MockVehicle implements Vehicle {
  
  void moveForward(int meters) {
    // ...
  }
}

abstract interface

interface修飾子の最も一般的な使い方は、純粋なインターフェースを定義することである。interface修飾子とabstract修飾子を組み合わせると、abstract interfaceクラスになります。

インターフェース・クラスと同様に、他のライブラリーは純粋インターフェースを実装することはできますが、継承することはできません。抽象クラスと同様に、純粋インターフェースも抽象メンバを持つことができます。

abstract interfaceだとabstractクラスと同じように、ロジックを定義しなくてもクラスを定義して、継承したクラスで、オーバーライドして、ロジックを実装することができます。

公式だけだとわかりにくいので海外の動画も見てみた

こちらの動画は参考になりました。
https://www.youtube.com/watch?v=dJ-YiCzPTPY

抽象メソッドを定義できない!

動画によると、ライブラリの定義時にインターフェイスの外にあるライブラリは、
インターフェイスを実装できますが、拡張はできません。

error code

'canWalk' must have a method body because 'AnimalInterface' isn't abstract.
Try making 'AnimalInterface' abstract, or adding a body to 'canWalk'.

AnimalInterface'は抽象化されていないので、'canWalk'はメソッドボディを持たなければならない。
AnimalInterface'を抽象化するか、'canWalk'にボディを追加してみてください。

ロジックを書くとエラーは解消される!

他のファイルでインターフェースクラスを継承しようとすると、エラーが出る!

The class 'AnimalInterface' can't be extended outside of its library because it's an interface class.dartinvalid_use_of_type_outside_library
interface class AnimalInterface
package:dart_zenn_cookbook/interface/animal_interface.dart

クラス「AnimalInterface」はインターフェース・クラスであるため、ライブラリの外部で拡張できません。
インターフェースクラス AnimalInterface
パッケージ:dart_zenn_cookbook/interface/animal_interface.dart

これは、extendsの場合でimplementsでは発生しない。

でも同じファイル内では継承はできる。

interface class AnimalInterface {

  void canWalk() {
    print('interface animal can walk');
  }
}

class Animal extends AnimalInterface {

  
  void canWalk() {
    print('animal can walk');
  }

  void canRun() {
    print('animal can run');
  }
}

void main() {
  final animal = Animal();
  animal.canWalk();
  animal.canRun();
}

まとめ

Dart3からinterfaceが使えるようになったが、今の所抽象クラスとして使ってしまうので、良い感じの使用例を思いつかない。
abstractと同じように使ってしまうので、これは設計では良い使用例だなと思えるものがないか考えているところです。

Discussion