dart で可変長引数を実現するためのパッケージ(dynamic_function)を作成しました。
そのことは以下の記事で紹介しましたが、DynamicFunction では名前付き引数もサポートされます。
例えば、以下のような(オプショナル引数と名前付き引数を共存させる)定義は dart3 ではできません。
GitHub の issue もご覧ください:
以下の例では x が必須の positional parameter で title がオプショナル引数、そして asJson が名前付き引数です。
void echo(dynamic x, [String? title], {bool? asJson}) {
}
DynamicFunction を使えば、「オプショナル引数と名前付き引数を共存させる」ことができます。
デモソースの実行結果では、asJson を指定したときに「abc」ではなくて「"abc"」とダブルクォートがついていることに留意してください。
とりあえず、デモ用のソースを提示しておきます(dart-sdk-3.7.2 と dart-sdk-3.9.0-14.0.dev で動作を確認しました。また flutter web, flutter windows desktop でも動作しました(flutter-sdk-3.29.3))。
name: qiita
description: A sample command-line application
version: 0.0.1
publish_to: none
environment:
sdk: ^3.7.2
dependencies:
dynamic_function: ^1.0.4
dev_dependencies:
import 'package:dynamic_function/dynamic_function.dart';
import 'dart:convert' as convert;
// void echo(dynamic x, [String? title], {bool? asJson});
// を目指しています
final dynamic echo = DynamicFunction((
List<dynamic> positional,
Map<Symbol, dynamic> named,
) {
if (positional.length < 1 || positional.length > 2) {
throw '${positional.length} arguments supplied to echo()';
}
dynamic x = positional[0];
String? title = positional.length == 2 ? positional[1] as String : null;
checkNamed(named, ['asJson']);
bool asJson =
named[Symbol('asJson')] == null ? false : named[Symbol('asJson')] as bool;
String json = (x is String) ? '`${x}`' : '${x}';
if (asJson) {
json = convert.jsonEncode(x);
}
if (title == null) {
print(json);
} else {
print('${title} ==> ${json}');
}
return null;
});
void main() {
final x = [11, null, 'abc'];
echo(x); // (1)
echo(x, 'x'); // (2)
echo(x, asJson: true); // (3)
echo(x, 'x', asJson: true); // (4)
//echo(); // 0 arguments supplied to echo()
//echo(x, 'x', 777); // 3 arguments supplied to echo()
}
/*
【実行結果】
[11, null, abc] // (1)
x ==> [11, null, abc] // (2)
[11,null,"abc"] // (3)
x ==> [11,null,"abc"] // (4)
*/
どうです。おもしろいでしょう?
ちなみに、
checkNamed(named, ['asJson']);
というのは、オプショナルな名前付き引数の名前のリストを第二引数に指定して間違った名前付き引数が指定された場合に例外を投げてくれます。
checkNamed(named, ['asJson'], ['requiredParam']);
とすると、'requiredParam' は必須の名前付き引数としてチェックされます。
不明な点があればコメントでどうぞ!