名前付きパラメータ・イディオム
名前付きパラメータ・イディオム(Named Parameter Idiom)は関数呼び出し時に引数名を明示するためのイディオムです。
名前付き引数・ラベル付き引数などの機能が存在しない言語で、名前付き引数と同等の仕組みを実現することが可能になります。
/* 名前付きパラメーターイディオム */
Person p = new Person()
.setFirstName("Tom")
.setLastName("Suzuki")
.setAge(24);
/* 従来の記法 */
Person p = new Person("Tom", "Suzuki", 24);
パラメータ名がFirstName
, LastName
, Age
という目に見える形で明示されている点が本イディオムの特徴です。
従来の記法Person("Tom", "Suzuki", 24)
では第一引数や第二引数、第三引数の意味が不明瞭でしたが、名前付きパラメータイディオムでは各引数の意味がメソッド名によって明確に記されるというメリットがあります。
また、本イディオムはパラメータを順不同で指定することも可能です。
// 問題ない
new Person()
.setAge(24)
.setLastName("Suzuki")
.setFirstName("Tom");
// 未定義の場合はエラー
Person p = new Person(24, "Suzuki", "Tom");
実現方法
名前付きパラメータ・イディオムの多くは、セッターメソッドをメソッドチェーンさせることで実現されています。
参考までにsetAge
のメソッドチェーンは以下のようなイメージで実装されることが多いです。
class Person {
int age;
Person setAge(int age) {
this.age = age;
return this;
}
}
セッターメソッドsetAge
で自身のインスタンスの参照を返している点が重要です。これによりメソッドの呼び出し結果に対してメソッド呼び出しを行うことが可能になります。
Person p = new Person();
// メソッドチェーン
p.setAge(1).setAge(2);
// やっていることはこちらと一緒
p.setAge(1);
p.setAge(2);
サンプルコード
参考までにJava言語による名前付き引数イディオムの例を載せておきます。
class Person {
int _age;
String _firstName, _lastName;
Person setAge(int age) { _age = age; return this; }
Person setFirstName(String s) { _firstName = s; return this; }
Person setLastName(String s) { _lastName = s; return this; }
void print() {
System.out.printf("%s %s (%d歳)", _firstName, _lastName, _age);
}
public static void main(String[] args) {
Person p = new Person().setFirstName("Tom")
.setLastName("Suzuki")
.setAge(24);
p.print();
}
}
user$ javac Person.java
user$ java Person
Tom Suzuki (24歳)
一般的なオブジェクト指向言語あれば、Java以外の言語でも同等のイディオムの実現が可能です。
参考までに、C++の場合は参照やポインタを用いてメソッドチェーンを実現させます。
struct Person {
int _age;
Person& setAge(int age) { _age = age; return *this; }
Person* withAge(int age) { _age = age; return this; }
};
Person p = Person().setAge(1).setAge(2);
Person* q = (new Person())->withAge(1)->withAge(2);
名前付き引数
余談ですが、「名前付き引数」という仕組みが言語側でサポートされている場合もあります。名前付き引数の仕組みを利用すれば、名前付きパラメータ・イディオムは不要になり、先程のコードも以下のように書けるようになります。
/* 本物の名前付き引数 */
new Person(firstName:"Tom", lastName:"Suzuki", age:24);
/* JavaやC++では使えない */
new Person("Tom", "Suzuki", 24);
名前付き引数のより詳しい説明や目的については、以下のページにしてください。