ファクトリコンストラクタ
CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 14/110。
ファクトリコンストラクタは、常に新しいインスタンスを作成するとは限らない特別なコンストラクタです。通常のコンストラクタとは異なり、ファクトリコンストラクタは既存のインスタンス、サブタイプ、あるいは(ヌル許容の場合)nullを返すことさえできます。これは factory キーワードを使用して宣言します。
class Logger {
static final Logger _instance = Logger._internal();
// プライベートな名前付きコンストラクタ
Logger._internal();
// ファクトリコンストラクタ
factory Logger() {
return _instance;
}
}
Logger log1 = Logger();
Logger log2 = Logger();
print(identical(log1, log2)); // trueこの例では、ファクトリコンストラクタは常に同じインスタンスを返します。何度 Logger() を呼び出しても、同一のオブジェクトが取得されます。このパターンは、シングルトンを実装するためによく使用されます。
ファクトリコンストラクタは、重要な点で通常のコンストラクタとは異なります。ファクトリコンストラクタは、新しいインスタンスを全く作成しない可能性があるため、this にアクセスできません。代わりに、オブジェクトを明示的に返す必要があります:
class Shape {
factory Shape(String type) {
if (type == 'circle') return Circle();
if (type == 'square') return Square();
return Rectangle();
}
}
class Circle extends Shape { Circle() : super._(); }
class Square extends Shape { Square() : super._(); }
class Rectangle extends Shape { Rectangle() : super._(); }ファクトリコンストラクタは、キャッシュされたオブジェクトを返したり、オブジェクトプールを実装したり、入力パラメータに基づいてどのサブタイプをインスタンス化するかを決定したりするなど、インスタンスの生成を制御する必要がある場合に便利です。
チャレンジ
簡単シンプルな文字列入力に基づいて、さまざまなタイプの通知を作成するファクトリコンストラクタを使用した通知システムを構築しましょう。
コードを整理するために、2つのファイルを作成します:
notification.dart: すべての通知タイプのベースとなるNotificationクラスを定義します。クラスには以下を含める必要があります:String messageフィールド- メッセージを初期化するプライベートな名前付きコンストラクタ
Notification._internal typeパラメータに基づいて異なる通知サブタイプを返すファクトリコンストラクタNotification(String type, String message):- type が
'email'の場合は、EmailNotificationを返します - type が
'sms'の場合は、SMSNotificationを返します - それ以外の場合は、
PushNotificationを返します
- type が
Sending: [message]と出力するsend()メソッド
同じファイル内に、Notification を継承する3つのサブクラスを作成します:
EmailNotification:send()をオーバーライドしてEmail: [message]と出力しますSMSNotification:send()をオーバーライドしてSMS: [message]と出力しますPushNotification:send()をオーバーライドしてPush: [message]と出力します
各サブクラスには、message を受け取り、super._internal(message) を使用して親クラスに渡すコンストラクタが必要です。
main.dart: 通知クラスをインポートし、ファクトリコンストラクタを使用して3つの通知を作成します:- メッセージが
'Welcome!'のメール通知 - メッセージが
'Your code is 1234'のSMS通知 - メッセージが
'New update available'のプッシュ通知
send()を呼び出します。- メッセージが
期待される出力:
Email: Welcome!
SMS: Your code is 1234
Push: New update availableチートシート
ファクトリコンストラクタは、factoryキーワードを使用して宣言される特別なコンストラクタで、常に新しいインスタンスを作成するとは限りません。通常のコンストラクタとは異なり、既存のインスタンス、サブタイプ、またはnullを返すことができます。
ファクトリコンストラクタはthisにアクセスできず、明示的にオブジェクトを返す必要があります。
シングルトンパターンの例:
class Logger {
static final Logger _instance = Logger._internal();
Logger._internal(); // プライベートな名前付きコンストラクタ
factory Logger() {
return _instance; // 常に同じインスタンスを返す
}
}
Logger log1 = Logger();
Logger log2 = Logger();
print(identical(log1, log2)); // true異なるサブタイプを返す例:
class Shape {
factory Shape(String type) {
if (type == 'circle') return Circle();
if (type == 'square') return Square();
return Rectangle();
}
}
class Circle extends Shape { Circle() : super._(); }
class Square extends Shape { Square() : super._(); }
class Rectangle extends Shape { Rectangle() : super._(); }ファクトリコンストラクタは、キャッシュされたオブジェクトを返す、オブジェクトプールを実装する、または入力パラメータに基づいてどのサブタイプをインスタンス化するかを決定するなど、インスタンスの作成を制御するのに役立ちます。
自分で試してみよう
import 'notification.dart';
void main() {
// TODO: メッセージが 'Welcome!' のメール通知を作成する
// TODO: メッセージが 'Your code is 1234' のSMS通知を作成する
// TODO: メッセージが 'New update available' のプッシュ通知を作成する
// TODO: 各通知に対して順番に send() を呼び出す
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4Null Safety
Null Safety 入門Nullable と Non-Nullable? 演算子と ! 演算子late キーワードと Null SafetyNull-Aware 演算子クラスにおける Null Safetyまとめ:ユーザープロフィールシステム10コレクションとジェネリクス
List, Set, Map の概要型安全なコレクションジェネリッククラスジェネリックメソッドジェネリクスの制約Iterable と Iteratorまとめ:ジェネリックなストレージ