Menu
Coddy logo textTech

抽象クラス

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

抽象クラスは、直接インスタンス化できないクラスです。他のクラスの設計図として機能し、サブクラスが従わなければならない共通の構造を定義します。abstract キーワードを使用して作成します。

abstract class Shape {
  String color;
  
  Shape(this.color);
  
  void describe() {
    print('A $color shape');
  }
}

class Circle extends Shape {
  double radius;
  
  Circle(String color, this.radius) : super(color);
}

void main() {
  // Shape s = Shape('red');  // エラー!抽象クラスはインスタンス化できません
  var circle = Circle('blue', 5.0);
  circle.describe();  // A blue shape
}

抽象クラスは、それ自体では存在するには一般的すぎる概念を扱う場合に便利です。「Shape(図形)」は概念ですが、それが円、長方形、あるいは三角形であるかを知らなければ、図形を描くことはできません。抽象クラスはすべての図形に共通する要素を定義し、具体的なサブクラスが詳細な内容を提供します。

抽象クラスは、依然として実装を持つ通常のメソッド(describe() など)やコンストラクタを持つことができる点に注意してください。サブクラスは、通常の継承と同じようにこれらを継承します。主な違いは、単に抽象クラス自体のインスタンスを作成できないという点です。つまり、具体的なサブクラスを使用する必要があります。

challenge icon

チャレンジ

簡単

抽象クラスがより具体的な型の設計図としてどのように機能するかを示す、乗り物システムを構築しましょう。すべての乗り物に共通する要素を定義する抽象基底クラスを作成し、それを具体的な乗り物の型で拡張します。

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

  • vehicle.dart: ここで乗り物の階層を定義します:
    • String brandint year プロパティを持つ abstract class Vehicle。両方の値を受け取るコンストラクタと、[brand] ([year]) を出力する displayInfo() メソッドを含めます。
    • Vehicle を継承し、int doors プロパティを追加する Car クラス。Beep beep! を出力する honk() メソッドを含めます。
    • Vehicle を継承し、bool hasSidecar プロパティを追加する Motorcycle クラス。Vroom! を出力する revEngine() メソッドを含めます。
  • main.dart: 乗り物ファイルをインポートし、抽象クラスがどのように機能するかを示します:
    • ブランド 'Toyota'、年 2022、ドア数 4Car を作成します。
    • その displayInfo() メソッド(Vehicleから継承)を呼び出します。
    • Doors: [doors] を出力します。
    • その honk() メソッドを呼び出します。
    • 空行を出力します。
    • ブランド 'Harley'、年 2021、hasSidecar falseMotorcycle を作成します。
    • その displayInfo() メソッドを呼び出します。
    • Has sidecar: [hasSidecar] を出力します。
    • その revEngine() メソッドを呼び出します。

Vehicle は抽象クラスであるため、直接インスタンスを作成することはできません。具体的なサブクラスのいずれかを使用する必要があります。CarMotorcycle はどちらも、抽象親クラスから displayInfo() メソッドを継承します。

期待される出力:

Toyota (2022)
Doors: 4
Beep beep!

Harley (2021)
Has sidecar: false
Vroom!

チートシート

抽象クラス(abstract class)は、直接インスタンス化できないクラスです。これは他のクラスの設計図として機能し、サブクラスが従うべき共通の構造を定義します。abstract キーワードを使用して作成します:

abstract class Shape {
  String color;
  
  Shape(this.color);
  
  void describe() {
    print('A $color shape');
  }
}

class Circle extends Shape {
  double radius;
  
  Circle(String color, this.radius) : super(color);
}

void main() {
  // Shape s = Shape('red');  // エラー!抽象クラスはインスタンス化できません
  var circle = Circle('blue', 5.0);
  circle.describe();  // A blue shape
}

抽象クラスは以下を持つことができます:

  • 実装を持つ通常のメソッド
  • コンストラクタ
  • プロパティ

サブクラスは、通常の継承と同様にこれらのメンバを継承します。主な違いは、抽象クラス自体のインスタンスを作成できないことです。具体的なサブクラスを使用する必要があります。

自分で試してみよう

import 'vehicle.dart';

void main() {
  // TODO: brand が 'Toyota'、year が 2022、doors が 4 の Car を作成する
  
  // TODO: car に対して displayInfo() を呼び出す
  
  // TODO: "Doors: [doors]" を出力する
  
  // TODO: car に対して honk() を呼び出す
  
  // TODO: 空行を出力する
  
  // TODO: brand が 'Harley'、year が 2021、hasSidecar が false の Motorcycle を作成する
  
  // TODO: motorcycle に対して displayInfo() を呼び出す
  
  // TODO: "Has sidecar: [hasSidecar]" を出力する
  
  // TODO: motorcycle に対して revEngine() を呼び出す
}
quiz icon腕試し

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

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