Menu
Coddy logo textTech

covariant キーワード

CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 61/110。

サブクラスでメソッドをオーバーライドする場合、Dartは通常、パラメータの型が完全に一致することを要求します。しかし、親クラスよりも具体的な型をサブクラスのメソッドで受け入れたい場合があります。covariantキーワードを使用すると、これが可能になります。

Animal クラスが別の Animal を受け取るメソッドを持っているシナリオを考えてみましょう。

class Animal {
  void chase(Animal other) {
    print('Chasing an animal');
  }
}

class Dog extends Animal {
  @override
  void chase(covariant Dog other) {
    print('Dog chasing another dog');
  }
}

covariant がないと、Dart は DogAnimal と同じ型ではないと警告します。パラメータの前に covariant を追加することで、Dart に「これがより具体的であることを知っており、正しい型のみが渡されるようにします」と伝えます。

これは、サブクラスが論理的に自身の種類のみを扱うべき場合に役立ちます:

void main() {
  Dog dog1 = Dog();
  Dog dog2 = Dog();
  
  dog1.chase(dog2);  // 成功:犬が別の犬を追いかける
}

ただし、注意が必要です。covariant を使用すると、型の安全性が実行時(ランタイム)へと移行します。親クラスの参照を介して誤った型でメソッドを呼び出すと、コンパイル時エラーではなく実行時エラーが発生します。渡される型に確信がある場合に使用してください。

challenge icon

チャレンジ

簡単

covariant キーワードを使用して、ペットが同じ種類のペットとしか遊べないようにするペット互換性システムを構築しましょう。各タイプが同じタイプのペットのみを受け入れる playWith メソッドを持つ、ペットの階層構造を作成します。

コードを2つのファイルに整理します:

  • pets.dart: ここでペットの階層を定義します:
    • String name プロパティとコンストラクタを持つ Pet クラス。[name] plays with [other.name] と出力する playWith(Pet other) メソッドを含めます。
    • Pet を継承し、covariant キーワードを使用して Cat のみを受け入れるように playWith をオーバーライドする Cat クラス。[name] and [other.name] chase yarn together と出力する必要があります。
    • Pet を継承し、covariant キーワードを使用して Dog のみを受け入れるように playWith をオーバーライドする Dog クラス。[name] and [other.name] fetch the ball together と出力する必要があります。
    • Pet を継承し、covariant キーワードを使用して Rabbit のみを受け入れるように playWith をオーバーライドする Rabbit クラス。[name] and [other.name] hop around together と出力する必要があります。
  • main.dart: ペットのファイルをインポートし、各ペットのタイプが自分の種類とだけ遊ぶ様子を示します:
    • 'Whiskers''Mittens' という名前の2つの Cat オブジェクトを作成し、Whiskers を Mittens と遊ばせます。
    • 'Buddy''Max' という名前の2つの Dog オブジェクトを作成し、Buddy を Max と遊ばせます。
    • 'Flopsy''Cotton' という名前の2つの Rabbit オブジェクトを作成し、Flopsy を Cotton と遊ばせます。

covariant キーワードを使用すると、各サブクラスでパラメータの型を Pet から特定の型に絞り込むことができ、同じ種類のペット間での型安全な相互作用が保証されます。

期待される出力:

Whiskers and Mittens chase yarn together
Buddy and Max fetch the ball together
Flopsy and Cotton hop around together

チートシート

covariantキーワードを使用すると、サブクラスは親クラスよりも具体的なパラメータ型でメソッドをオーバーライドできます。

covariantがない場合、Dartではメソッドをオーバーライドする際にパラメータ型が完全に一致する必要があります。covariantを使用すると、サブクラスでパラメータ型を絞り込むことができます:

class Animal {
  void chase(Animal other) {
    print('Chasing an animal');
  }
}

class Dog extends Animal {
  @override
  void chase(covariant Dog other) {
    print('Dog chasing another dog');
  }
}

これは、サブクラスが自身の型のみを扱う必要がある場合に便利です:

void main() {
  Dog dog1 = Dog();
  Dog dog2 = Dog();
  
  dog1.chase(dog2);  // Works: Dog chasing another dog
}

重要: covariantを使用すると、型安全性がコンパイル時から実行時に移行します。親クラスの参照を介して間違った型でメソッドを呼び出すと、コンパイルエラーではなく実行時エラーが発生します。

自分で試してみよう

import 'pets.dart';

void main() {
  // TODO: 'Whiskers' と 'Mittens' という名前の 2 つの Cat オブジェクトを作成します
  // 次に Whiskers を Mittens と遊ばせます
  
  
  // TODO: 'Buddy' と 'Max' という名前の 2 つの Dog オブジェクトを作成します
  // 次に Buddy を Max と遊ばせます
  
  
  // TODO: 'Flopsy' と 'Cotton' という名前の 2 つの Rabbit オブジェクトを作成します
  // 次に Flopsy を Cotton と遊ばせます
  
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン