コンストラクタと継承
CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 41/110。
子クラスが親クラスを継承する場合、継承されたフィールドを適切に初期化するために、親のコンストラクタを呼び出す必要があります。Dartは、superを使用した初期化子リストを通じて、これを処理するための柔軟な方法を提供しています。
親クラスに引数付きのコンストラクタがある場合、子クラスはそれを明示的に呼び出す必要があります:
class Person {
String name;
int age;
Person(this.name, this.age);
}
class Student extends Person {
String school;
Student(String name, int age, this.school) : super(name, age);
}Dart 2.17 では、パラメータを親コンストラクタに直接渡すための、より簡潔な構文である super パラメータ が導入されました:
class Student extends Person {
String school;
// super.name と super.age は Person のコンストラクタに直接渡されます
Student(super.name, super.age, this.school);
}名前付きコンストラクタを使用する場合、どの親コンストラクタを呼び出すかを指定します。
class Employee extends Person {
String department;
Employee(super.name, super.age, this.department);
Employee.intern(String name, this.department) : super(name, 18);
}基本的なルールは単純です。子が独自のプロパティを追加する前に、親が完全に初期化されていなければなりません。従来の super() 呼び出しを使用する場合でも、新しいスーパーパラメータを使用する場合でも、Dart は継承チェーンが親から子へと適切に構築されることを保証します。
チャレンジ
簡単継承においてコンストラクタがどのように機能するかを実証する、製品在庫システムを構築しましょう。異なる製品タイプがベースとなる製品クラスを継承し、それぞれが親コンストラクタを通じて適切に初期化される階層構造を作成します。
コードは2つのファイルに分けて構成します:
product.dart: ここで製品の階層を定義します:String nameとdouble priceプロパティ、両方の値を受け取るコンストラクタ、および[name]: $[price]を出力するinfo()メソッドを持つProductクラス。Productを継承し、String authorプロパティを追加したBookクラス。スーパーパラメータを使用して、nameとpriceを親コンストラクタに転送します。Productを継承し、int warrantyプロパティ(月単位)を追加したElectronicsクラス。初期化リスト内で伝統的なsuper()呼び出しを使用して、親に値を渡します。
main.dart: 製品ファイルをインポートし、両方のコンストラクタ継承アプローチを実証します:- 名前が
'Dart Essentials'、価格が29.99、著者が'Jane Smith'のBookを作成します。 - その
info()メソッドを呼び出し、次にAuthor: [author]を出力します。 - 空行を出力します。
- 名前が
'Wireless Mouse'、価格が45.50、保証期間が24のElectronicsを作成します。 - その
info()メソッドを呼び出し、次にWarranty: [warranty] monthsを出力します。
- 名前が
どちらの子クラスも、オーバーライドすることなく Product から info() メソッドを継承します。主な違いは親コンストラクタの呼び出し方法にあります。Book はよりクリーンなスーパーパラメータ構文を使用し、Electronics は初期化リストで super() を使用する伝統的なアプローチを使用します。
期待される出力:
Dart Essentials: $29.99
Author: Jane Smith
Wireless Mouse: $45.5
Warranty: 24 monthsチートシート
子クラスが親クラスを継承する場合、継承されたフィールドを適切に初期化するために、親クラスのコンストラクタを呼び出す必要があります。
従来の方式 - 初期化子リストで親コンストラクタを明示的に呼び出す:
class Person {
String name;
int age;
Person(this.name, this.age);
}
class Student extends Person {
String school;
Student(String name, int age, this.school) : super(name, age);
}Superパラメータ (Dart 2.17+) - パラメータを親コンストラクタに直接渡す:
class Student extends Person {
String school;
Student(super.name, super.age, this.school);
}名前付きコンストラクタ - 呼び出す親コンストラクタを指定する:
class Employee extends Person {
String department;
Employee(super.name, super.age, this.department);
Employee.intern(String name, this.department) : super(name, 18);
}自分で試してみよう
import 'product.dart';
void main() {
// TODO: 以下の内容でBookを作成してください:
// - name: 'Dart Essentials'
// - price: 29.99
// - author: 'Jane Smith'
// TODO: bookのinfo()メソッドを呼び出してください
// TODO: "Author: [author]" を出力してください
// TODO: 空行を出力してください
// TODO: 以下の内容でElectronicsを作成してください:
// - name: 'Wireless Mouse'
// - price: 45.50
// - warranty: 24
// TODO: electronicsのinfo()メソッドを呼び出してください
// TODO: "Warranty: [warranty] months" を出力してください
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4Null Safety
Null Safety 入門Nullable と Non-Nullable? 演算子と ! 演算子late キーワードと Null SafetyNull-Aware 演算子クラスにおける Null Safetyまとめ:ユーザープロフィールシステム10コレクションとジェネリクス
List, Set, Map の概要型安全なコレクションジェネリッククラスジェネリックメソッドジェネリクスの制約Iterable と Iteratorまとめ:ジェネリックなストレージ