Dartのジェネリクスについて

概要

ジェネリクスとは、型をコンパイル時に決定する書き方である。
<>の中に型を入れる。

以下にコード例を示す。

void sample<T>(T argment){
	T result = argment;
	return result;
}
 
R sample<T,R>(T argment){
	R result = argment as R;
	return result;
}

Dartでは、関数の横に<T>と記述するとジェネリクスとなる。
この場合、Tという型が認識される。

返り値や引き数にこのジェネリクスを定義することが出来る。

Tip

T以外にも使用者が文字を決めることが出来る。
SRTYPEなどでもよい。

このT関数呼び出し時に決定することが出来る。

以下にコード例を示す。

final intValue = sample<Int>(12);                //sample関数のTはInt型と認識される
final strValue = sample<String>("Hello World");  //sample関数のTはString型と認識される
 
void sample<T>(T argment){
	T result = argment;
	return result;
}

このTextendsを使用することで型を制限できる。

final intValue = sample<Int>(12);                
final strValue = sample<String>("Hello World");  //エラー
 
void sample<T extends Int>(T argment){
	T result = argment;
	return result;
}

クラス

クラスにも使用することが出来る。
クラスに使用するとメソッド複数で設定したジェネリクスを使用することが出来る。

以下にコード例を示す。

class SampleClass<T>{
	late final T value; 
	
	SampleClass(T arg){
		value = arg;
	}
}

デザインパターンであるストラテジパターンにも応用することが出来る。

使用例

一番このジェネリクスが真価を発揮するのはDB操作の際である。

DB操作では、本来テーブルごとに操作するクラスを作成しなければいけないが、このジェネリクスを使用すると一つで十分となる。

以下にコード例を示す。

class RealmIOManager extends RealmIOManagerInterface {
	final realmInsFac = RealmInstanceFactory();
	final _reader = _DataReader();
	final _adder = _DataAdder();
	late Realm realm;
	
	RealmIOManager(SchemaObject schemaObjectArg) {
		realm = realmInsFac.createRealmIns(schemaObjectArg: schemaObjectArg);
	}
	
	@override
	Future<void> add<T extends RealmValidatedSchemaValueInterface>(
	{required RealmValidatedSchemaValueInterface dataInsToAddArg}) async {
		_adder.add<T>(realm: realm, dataInsToAddArg: dataInsToAddArg);
	}
	
	@override
	List<SCHEMA> readAll<SCHEMA extends RealmObject>() {
		RealmIOResults results = _reader.readAll<SCHEMA>(realm: realm);
		return results.payload;
	}
	
	@override
	SCHEMA searchById<SCHEMA extends RealmObject>({required ObjectId idArg}) {
		var result = _reader.searchById<SCHEMA>(realm: realm, idArg: idArg);
		return result.payload;
	}
	
	@override
	SCHEMA searchByName<SCHEMA extends RealmObject>({required ObjectId idArg}) {
		var result = _reader.searchById<SCHEMA>(realm: realm, idArg: idArg);
		return result.payload;
	}
	
	@override
	void delete<SCHEMA extends RealmObject>({required ObjectId idArg}) {
		var obj = searchById<SCHEMA>(idArg: idArg);
		realm.write(() => realm.delete<SCHEMA>(obj));
	}
	
	@override
	void deleteAll<SCHEMA extends RealmObject>() {
		realm.write(() => realm.deleteAll<SCHEMA>());
	}
}

このコードではジェネリクスを使用してDB操作をクラス1つで完結させている。