プログラム学習室 http://studyhallweb.com/

Dart言語: Class

基本的なクラス

Classの基本的な使い方
// 基本のクラス
class calAdd {
  num n;
  add(num a, num b) {
    n = a + b;
  }
}

void main() {
  calAdd cTest = new calAdd();
  cTest.add(1, 2);
  print('1 + 2 = ${cTest.n}');  // 1 + 2 = 3 が出力される
}					

クラスの継承

クラスを継承すると基本のクラスに機能を追加することが出来ます。 継承は extedns を用います。
// 基本のクラス
class calBase {
  num n;
  add(num a, num b) {
    n = a + b;
  }
  cal(num a, num b) {
    n = a + b;
  }
}

// クラスの継承
class calExt extends calAdd {
// メソッドの追加
  sub(num a, num b) {
    n = a - b;
  }
// メソッドのオーバーライト
  cal(num a, num b) {
    n = a * b;
  }
}

void main() {
  calBase cal01 = new calBase();
  calExt cal02 = new calExt();

  cal01.add(3, 2);
  print('基底クラス.add(3, 2) = 3 + 2 = ${cal01.n}');
  cal02.add(3, 2);
  print('継承クラス.add(3, 2) = 3 + 2 = ${cal02.n}');

  cal02.sub(3, 2);
  print('継承クラス.sub(3, 2) = 3 - 2 = ${cal02.n} (追加されたメソッド)');

  cal01.cal(3, 2);
  print('基底クラス.cal(3, 2) = 3 + 2 = ${cal01.n}');
  cal02.cal(3, 2);
  print('継承クラス.cal(3, 2) = 3 * 2 = ${cal02.n} (オーバーライトされている)');
}
				

実行結果

基底クラス.add(3, 2) = 3 + 2 = 5
継承クラス.add(3, 2) = 3 + 2 = 5

継承クラス.sub(3, 2) = 3 - 2 = 1 (追加されたメソッド)

基底クラス.cal(3, 2) = 3 + 2 = 5
継承クラス.cal(3, 2) = 3 * 2 = 6 (オーバーライトされている)
				

複数クラスの継承

複数のクラスを同時に継承することが出来ます。
class calAdd {
  num n;
  add(num a, num b) {
    n = a + b;
  }
}
class calSubtract {
  num n;
  sub(num a, num b) {
    n = a - b;
  }
}
class calMultiple {
  num n;
  multiple(num a, num b){
    n = a * b;
  }
}

  // 複数のクラスを継承(With の後に列記)
  class calExts extends calAdd with calSubtract, calMultiple {
  num ans() {
    return n;
  }
}

void main() {
  calExts cTest = new calExts();
  cTest.add(1, 2);
  print('1 + 2 = ${cTest.n}');  // 1 + 2 = 3 が出力される
  cTest.sub(3, 2);
  print('3 - 2 = ${cTest.n}');  // 3 - 2 = 1 が出力される
  cTest2.multiple(3, 4);
  print('3 * 4 = ${cTest.ans()}');    // 3 * 4 = 12 が出力される

}					

クラスの継承 コンストラクタ

クラスの継承において、コンストラクタの引数はそのままでは引き継がれません
// 基本のクラス
class calBase {
  num n;
  num a, b;
  calBase([a = 1, b = 1]) {
    n = a + b;
  }
  ans([String s]) {
    if (s == null) {
      print('n = $n');
    } else {
      print('n = $n : $s');
    }
  }
}
// 継承クラス
class calExt1 extends calBase {
}
class calExt2 extends calBase {
  calExt2([a = 1, b = 1]) {
  }
}
class calExt3 extends calBase {
  calExt3([a = 1, b = 1]) : super(a, b) {
  }
}
class calExt4 extends calBase {
  calExt4([a = 2, b = 2]) : super(a, b) {
  }
}

void main() {
  calBase cal00 = new calBase();
  calBase cal00a = new calBase(2, 3);
  calExt1 cal01 = new calExt1();
// calExt1 cal01a = new calExt1(2, 3); これはエラー
  calExt2 cal02 = new calExt2(2, 3);
  calExt3 cal03 = new calExt3(2, 3);
  calExt4 cal04 = new calExt4();

  cal00.ans('calBase()');
  cal00a.ans('calBase(2,3)');
  cal01.ans('calExt1()');
  cal02.ans('calExt2(2,3)');
  cal03.ans('calExt3(2,3)');
  cal04.ans('calExt4()');
}

実行結果

n = 2 : calBase()
n = 5 : calBase(2,3)
n = 2 : calExt1()
n = 2 : calExt2(2,3)
n = 5 : calExt3(2,3)
n = 4 : calExt4()
				

calExt1 のように単純に継承しただけでは、コンストラクタに引数を指定することが出来ません。
calExt1 cal01a = new calExt1(2, 3); はエラーになってしまいます。

継承したクラスの中でもコンストラクタを定義しないといけません。calExt2 にように再定義すれば、calExt2(2, 3)はエラーにはなりません。
しかし、実行結果は意図したものにならず、引数が正しく渡されていないことが分かります。
calExt2(2, 3)は、n = 5 にはなっていません。

引数を基のクラスのコンストラクタに正しく引き渡すには super を付けます。
calExt3([a = 1, b = 1]) : super(a, b) とすることで、calExt3(2, 3) の結果、引数 2 と 3 が正しく引き渡され n = 2 + 3 = 5 となります。

calExt4([a = 2, b = 2]) : super(a, b) のように引数のデフォルト指定を変更することも可能です。

super をつけることは teratailで教えていただきました。

抽象クラス

抽象クラスを使うことで、条件によってクラスを使い分けることが出来ます。
次のプログラムは条件によってインスタンスを使い分けています。
普通のクラスでは if文の中でインスタンス化した場合、可視範囲が限られるため、if文の外では無効になります。
そのため if文で条件を分けても if分の後(外)で共通の処理が書けません。

基底クラスは abstract をつけて宣言します。
/**
* 基底クラス
*/
abstract class base {
  exe();
}

class typeA extends base {
  exe() {
    print('Tyep A');
  }
}
class typeB extends base {
  exe() {
    print('Tyep B');
  }
}

main(List<String> arguments) {
  base cls;

  if (arguments[0] == 'A') {
    cls = new typeA();
  } else {
    cls = new typeB();
  }
  cls.exe();  // if文の外で使える = 条件によって使い分けが可能

}