継承関係を持つクラスで流れるようなインターフェイス
流れるようなインターフェイス(fluent interface)とは
setterで戻り値をvoidじゃなくてthisを戻すようにするとメソッドチェーン出来て便利ですねという話。
Martin Fowler's Bliki in Japanese - 流れるようなインターフェース
例:
public class Person { private String name; private int age; public String getName() { return name; } public Person setName(String name) { this.name = name; return this; } public int getAge() { return age; } public Person setAge(int age) { this.age = age; return this; } }
まあ、継承を考えなければ、上のようにsetterでthisを戻せば良い。
呼び出す時はこんな感じ。
Person person = new Person(); person.setAge(17).setName("H.P.Lovecraft");
流れるようなインターフェイスって何てスッキリして便利なんだろう!感激・・・と思っていた時期もありました。継承を意識するまでは。
継承関係を持つクラスで流れるようなインターフェイス
では、流れるようなインターフェイスでPersonのサブクラスEmployeeを定義してみましょう
public class Employee extends Person { private int empId; private String division; public int getEmpId() { return empId; } public Employee setEmpId(int empId) { this.empId = empId; return this; } public String getDivision() { return division; } public Employee setDivision(String division) { this.division = division; return this; } }
____ / \ /\ キリッ . / (ー) (ー)\ / ⌒(__人__)⌒ \ | |r┬-| | \ `ー'´ / ノ \ /´ ヽ | l \ ヽ -一''''''"~~``'ー--、 -一'''''''ー-、. ヽ ____(⌒)(⌒)⌒) ) (⌒_(⌒)⌒)⌒)) ____ /_ノ ヽ、_\ ミ ミ ミ o゚((●)) ((●))゚o ミ ミ ミ どこが難しいんだおwwww /⌒)⌒)⌒. ::::::⌒(__人__)⌒:::\ /⌒)⌒)⌒) | / / / |r┬-| | (⌒)/ / / // | :::::::::::(⌒) | | | / ゝ :::::::::::/ | ノ | | | \ / ) / ヽ / `ー'´ ヽ / / | | l||l 从人 l||l l||l 从人 l||l ヽ -一''''''"~~``'ー--、 -一'''''''ー-、 ヽ ____(⌒)(⌒)⌒) ) (⌒_(⌒)⌒)⌒))
じゃあ使ってみようか
Employee emp = new Employee(); emp.setAge(17).setEmpId(10)
setEmpId(10)まで書いた所で、IDE上でコンパイルエラー警告が出るはず。何でって?setAgeはPersonクラスの皮をかぶったインスタンスを戻すし、setEmpIdメソッドはPersonクラスでは定義されてないからね。
____ / \ / _ノ ヽ、_ \ / o゚((●)) ((●))゚o \ 流れるようなインターフェイスって難しいお | (__人__) | \ ` ⌒´ / ____ / \ / _ノ ヽ、_ \ / o゚⌒ ⌒゚o \ 静的型言語ってこんなことすら出来ないのかお。Javaはオワコン | (__人__) | \ ` ⌒´ /
んなこと無い。ジェネリクス使おう。
public class Person <T>{ private String name; private int age; public String getName() { return name; } public T setName(String name) { this.name = name; return (T) this; } public int getAge() { return age; } public T setAge(int age) { this.age = age; return (T) this; } }
public class Employee extends Person<Employee> { private int empId; private String division; public int getEmpId() { return empId; } public Employee setEmpId(int empId) { this.empId = empId; return this; } public String getDivision() { return division; } public Employee setDivision(String division) { this.division = division; return this; } }
呼び出しはこんな感じ。
Employee emp = new Employee(); emp.setAge(17). setEmpId(10). setName("H.P.Lovecraft"). setDivision("Unspeakable Div.");
PersonのメソッドであるsetAgeやsetNameがEmployeeクラスのインスタンスを戻しているので、setEmpIdやsetDivisionを呼び出してもコンパイルエラーにならない。
____ / ノ \\ / (●) (●)\ / ∪ (__人__) \ 凄く…微妙です | ` ⌒´ | \ /⌒)⌒)⌒) //⌒)⌒)⌒) ノ | / / / (⌒) / / / / /´ | :::::::::::(⌒) ゝ :::::::::::/ | l | ノ / ) / ヽ ヽ_ヽ /' / / ヽ __ / / /
漏れもそう思う。
追記: AA記法を使っても何故か崩れまくるのは、はてなブログのせい?
再度追記:どうもはてなblog側でAA記法を上手く扱えてないっぽい(preタグのclassが変で、はてなダイアリーだと"ascii-art"クラスになるはずが"lang-"になってる。)
メニューの「管理」->「デザイン」->「カスタマイズ」->「デザインCSS」に以下のCSSを追加して対応。
pre.lang- { font-family: "MS Pゴシック", "MS PGothic", Mona, IPAMonaPGothic, 'Textar', sans-serif!important; font-size: 12pt; line-height: 18px; }