libro
www.tuyano.com
初心者のためのDart 2入門

クラスを更に掘り下げる! (6/6)

作成:2018-04-21 09:29
更新:2018-04-21 09:29

■演算子のオーバーライド

新たにクラスを作成し、そのインスタンスを利用する場合、考えておきたいのが「インスタンスどうしの演算」についてです。

自分で作成したクラスのインスタンスは、例えば==で比較したり、+や-で足し算や引き算したりできません。が、こうした基本的な演算が行えると、オブジェクトの使い勝手は格段に良くなります。

Dartでは、演算子のオーバーライドに対応しています。オーバーライドというのは、スーパークラスにあるメソッドをサブクラスで上書きすることでしたが、演算子のオーバーライドというのは、「演算子の定義をクラスに用意することで、演算子の働きを変更する」ことです。これは以下のように記述をします。
戻り値 operator 演算子 (dynamic 変数 ) {
    ……略……
}
演算子のオーバーライドもメソッドと同じような形で記述をします。ただし、一般のメソッドと異なるのは、戻り値の指定の後に「operator」というキーワードが用意されることです。これにより、このメソッドが演算子の処理を定義するものだとわかります。

また、一般的な演算子は、他のオブジェクトとの演算を行うものなので、引数には「dynamic」というタイプを指定します。これは、特定のタイプに固定せず、ダイナミックにタイプが設定される場合に用います。

これは、実例を見てみないとピンとこないでしょう。下に、MyDataクラスに==と+演算子の処理を追加した例を挙げておきます。ここでは、3つのインスタンスを作成し、それらを==で比較したり、+で加算したりしています。

ここで用意している演算子関係のメソッドがどうなっているのか見てみましょう。

●==演算子の処理
  bool operator ==(dynamic other) {
    if (other is MyData){
      var f1 = this.name == other.name;
      var f2 = this.mail == other.mail;
      var f3 = this.age == other.age;
      return f1 == f1 && f2 && f3;
    } else {
      return false;
    }
  }
==のような比較演算子は、結果をboolで返しますので戻り値はboolです。ここでは、引数で渡されるdynamic変数がMyDataインスタンスかどうかチェックし、そうだった場合は、name, mail, ageのそれぞれの値が同じかチェックして結果を返しています。「何をチェックすれば、2つのインスタンスを等しいと判断していいいか」を考えれば、処理の内容はわかるでしょう。
  
●+演算子の処理
  MyData operator +(dynamic other){
    if (other is MyData){
      var re = new MyData();
      re.name = this.name + ' & ' + other.name;
      re.mail = this.mail + ', ' + other.mail;
      re.age = this.age + other.age;
      return re;
    } else {
      return null;
    }
  }
+などの四則演算の演算子は、2つのMyDataを演算した結果のMyDataを返すような形になっているのが自然でしょう。そこで戻り値はMyDataにしてあります。これも、やはり最初に引数のオブジェクトがMyDataかどうかチェックし、そうだった場合は、name, mail, ageのそれぞれの値を足したMyDataインスタンスを作って返しています。MyDataではなかった場合は、ここではnullを返すようにしておきました。

――こんな具合に、演算子をオーバーライドできると、インスタンスを==で比較したり、+で足し算したりといろいろ利用が広がります。

※プログラムリストが表示されない場合

AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。

●プログラム・リスト●

void main() {
  MyData taro = new MyData.make('Taro', 'taro@yamada', 35);
  MyData hanako = new MyData.make('Hanako', 'hanako@flower', 28);
  MyData hanako2 = new MyData.make('Hanako', 'hanako@flower', 28);
  taro.printData();
  hanako.printData();
  hanako2.printData();
  print(taro == hanako);
  print(hanako == hanako2);
    var plus_obj = taro + hanako;
  plus_obj.printData();
}

class MyObj {
  String name;
  String mail;
  num age;
  
  Map getData(){
    return {'name':this.name, 'mail':this.mail, 'age':this.age};
  }
}

class MyData extends MyObj {
  
  MyData() : this.make('noname', 'no@mail', 0);
  
  MyData.make(String name, String mail, num age){
    this.name = name;
    this.mail = mail;
    this.age = age;
  }
  
  void printData(){
    String re = '<MyObj "' + this.name + '" [' + this.mail + '](' + 
          this.age.toString() + ')>';
    print(re);
  }
  
  bool operator ==(dynamic other) {
    if (other is MyData){
      var f1 = this.name == other.name;
      var f2 = this.mail == other.mail;
      var f3 = this.age == other.age;
      return f1 == f1 && f2 && f3;
    } else {
      return false;
    }
  }
  
  MyData operator +(dynamic other){
    if (other is MyData){
      var re = new MyData();
      re.name = this.name + ' & ' + other.name;
      re.mail = this.mail + ', ' + other.mail;
      re.age = this.age + other.age;
      return re;
    } else {
      throw new Exception('cannot add!');
    }
  }

}


※関連コンテンツ

「初心者のためのDart 2入門」に戻る