Dartのクラスの継承と@overrideとは?

19360 ワード

知ってはいるけどビジネスロジック考えながら、勉強してみた🤔

今回は、ドラクエで出てくる職業を参考にコードを書いてみた😅

profession.dart

// 職業を意味するプロフェッションクラス
class Profession {
  final String _professionName; // 職業の名前を表すプロフェショナルプロパティ
  final String _ability; // 能力を表すアビリティプロパティ

  Profession(this._professionName, this._ability);

  String get professionName => _professionName;
  String get ability => _ability;

  // 技能を表示するスキルメソッド
  List skill(e) {
    return e;
  }
  // 経験のある職業を表示するエクスペリアンスメソッド
  List experience(e) {
    return e;
  }
}

こちらのコードは親クラスProfessionを継承しているので、プロパティとメソッド書かなくても使える。

warrior.dart

import 'profession.dart';
// 職業戦士を表すウォーリアークラス
class Warrior extends Profession {
  Warrior(String _professionName, String _ability)
      : super(_professionName, _ability);
}

wizard.dart

import 'profession.dart';
// 職業魔法使いを表すウイザードクラス
class Wizard extends Profession {
  Wizard(String _professionName, String _ability)
      : super(_professionName, _ability);
}

こちらのコードは@overrideを使ってメソッドを上書きして、初期値を加えている。
magic_warrior.dart

import 'profession.dart';
// 職業魔法戦士を表すウイザードクラス
class MagicWarrior extends Profession {
  MagicWarrior(String _professionName, String _ability)
      : super(_professionName, _ability);

  // 親クラスの技能を表示するスキルメソッドを上書き
  
  List skill(e) {
    return ["魔神斬り", "メタル斬り", "火炎斬り", "ホイミ", "マヌーサ", "メダパニ"];
  }
  // 親クラスの経験のある職業を表示するエクスペリアンスメソッドを上書き
  
  List experience(e) {
    return ["戦士", "魔法使い"];
  }
}

インスタンスを作って、子供のクラスのメソッドを実行するコード

sample.dart

import 'dart:math';

import 'magic_warrior.dart';
import 'profession.dart';
import 'warrior.dart';
import 'wizard.dart';

void main() {
  Profession warrior = Warrior("戦士", "剣でモンスターと戦う人");
  print(warrior.professionName);
  print(warrior.ability);
  var skillA = warrior.skill(["魔神斬り", "メタル斬り", "火炎斬り"]);
  print(skillA);
  var experienceA = warrior.experience(["戦士"]);
  print(experienceA);

  Wizard wizard = Wizard("魔法使い", "魔法でモンスターと戦う人");
  print(wizard.professionName);
  print(wizard.ability);
  var skillB = wizard.skill(["ホイミ", "マヌーサ", "メダパニ"]);
  print(skillB);
  var experienceB = wizard.experience(["魔法使い"]);
  print(experienceB);

  MagicWarrior magicWarrior = MagicWarrior("魔法戦士", "剣と魔法でモンスター戦う人");
  print(magicWarrior.professionName);
  print(magicWarrior.ability);
  var skillC = magicWarrior.skill(e);
  print(skillC);
  var experienceC = magicWarrior.experience(e);
  print(experienceC);
}

実行結果

戦士
剣でモンスターと戦う人
[魔神斬り, メタル斬り, 火炎斬り]
[戦士]
魔法使い
魔法でモンスターと戦う人
[ホイミ, マヌーサ, メダパニ]
[魔法使い]
魔法戦士
剣と魔法でモンスター戦う人
[魔神斬り, メタル斬り, 火炎斬り, ホイミ, マヌーサ, メダパニ]
[戦士, 魔法使い]
Exited

コードの解説
Dartで、finalとは定数なのですが、constもあります。役割が違うことに昨日学習して気づきました!

人から教えてもらった表現です。わかりやすい👇
一度インスタンスを生成すると、Setterが存在しないため変更不可能なフィールドとなる。そう言った場合はfinal修飾子を付与します!

  • final⇨プログラムが実行されて代入されたあとに変更不可
  • const⇨コンパイル時に値が代入され、それ以降変更不可

**superとは何か?**🤔

Javaでもあったな。super()とは?
あるクラスをインスタンス化する際には、何もしなくとも親クラスのコンストラクタが勝手に呼ばれるようになっているわけですが、勝手に呼ばせるのではなく、自分でコーディングすることで親クラスのコンストラクタを呼ぶことも出来ます。

Dartではどんな動きをするのか?

  • Warriorクラスのコンストラクタ
  • 同時に親クラス(superが親の意味)にも設定を行います
class Warrior extends Profession {
  Warrior(String _professionName, String _ability)
      : super(_professionName, _ability);
}

こちらのコードは思いつきで書いてみました😅
引数を入れて、戻り値で返すことができるコード。まさか動くとは!
型はListなので配列ですね。

// 技能を表示するスキルメソッド
  List skill(e) {
    return e;
  }
  // 経験のある職業を表示するエクスペリアンスメソッド
  List experience(e) {
    return e;
  }

VScodeの機能で見てみると面白いことがわかりました!

dynamic型のListとdynamic型の引数のメソッドになっている。
String型にしてみようとしたのですが、エラーになってしまうので、型は付けませんでした!

改めて学習をしてみた感想

Flutterでアプリを作っているときに、@override、setState()、initState()、何これ???
Dartの文法が分からなかったので、何をしているのか理解ができなかった😭
最近少しづつですが、Flutterのソースコードが何をしているのかが理解できるようになってきました。