search
LoginSignup
0

posted at

updated at

Organization

Dartでのmixinと継承の使い分け

iPresenceでは複数種類のロボットを1つのモバイルアプリからzoom等と連携して遠隔操作するアプリを開発しています。
その際アプリ側では1つのエントリーポイントから設定されたロボットにコマンドを渡しつつ各ロボット固有の機能も動作させる必要があります。

アートボード 1.png

そこで全てのロボットに共有の動作とロボット固有の機能の動作を切り分けつつシンプルに書くためにDartのmixin/withの機能を使用します。

mixinと継承の違い

抽象クラス(abstract)を継承するのとmixinクラスを使用する際の違いは以下になります

抽象クラスの継承

  • すべてのメソッドをオーバーライドし実装する必要がある。
  • 1つの子クラスに対して1つの親クラスしか渡せない

mixin

  • 必ずしもメソッドをオーバーライドする必要はない
  • 1つのクラスに対して複数mixinすることができる
  • コンストラクタを定義できない

このようにそれぞれにメリット/デメリットがありますが、うまく使い分けることで効果を発揮します

実装

以下の様に共通する機能と固有の機能の切り分けに使うことができます。


// 共通機能を定義したmixinクラス
// ロボットを操作するメソッドを仮実装する
mixin RobotCtlRepository{
  void robotControl(){
    throw UnimplementedError();
  }
}

mixin RobotSetUpRepository{
  void setup(){
    throw UnimplementedError();
  }

  void deleteSetting(){
    throw UnimplementedError();
  }
}

// RobotA の固有機能のクラス
// RobotCtlRepository をmixinすることで robotControlメソッドも内包される
abstract class RobotARepository with RobotCtlRepository{
  Future<void> robotAFunc();
}

// 同じようにRobotB,Cもそれぞれ専用の抽象クラスを定義してmixinさせる
// mixinをするので複数のクラスRobotCtlRepositoryとRobotSetUpRepositoryをもたせることもできる
abstract class RobotBRepository with RobotCtlRepository, RobotSetUpRepository{
  String robotBFunc();
}

abstract class RobotCRepository with RobotCtlRepository, RobotSetUpRepository{
  void robotCFunc();
}

このように抽象クラスに対してmixinすることで共有の機能をもたせることができるようになります。
またこれに対する実装は以下のようになります。

// メソッドの実装

class RobotARepositoryImpl extends RobotARepository{
  @override
  Future<void> robotAFunc() async{
    await robot_a_function;
  }

  @override
  void robotControl(){
    robotA.move();
  }
}

class RobotBRepositoryImpl extends RobotARepository{
  @override
  String robotBFunc(){
    return "robotB";
  }

  @override
  void robotControl(){
    robotB.pan();
  }

  @override
  void setup(){
    robotB.setup();
  }

  @override
  void setup(){
    robotB.deleteSetting();
  }
}

class RobotCRepositoryImpl extends RobotARepository{
  @override
  void robotCFunc(){
    robot_c_function;
  }

  @override
  void robotControl(){
    robotC.tilt();
  }

  @override
  void setup(){
    robotC.setup();
  }
  // mixinなのでdeleteSettingはオーバーライドしなくてもいい
}

終わりに

mixinと継承を組み合わせ、使い分けることで柔軟で拡張性のある実装ができるようになります。
どのように切り分けるかなどは規模や設計・開発方針にもよってくるので適宜使っていくのがいいと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0