Twitter: @kinaba
一個前の記事にytさんから それE って 突っ込みいただきました。On the Eiffel approach to typing など調べてみると
x: like y
と書くと、yが派生クラスで基底クラスで違う型だったらそれに合わせてxの型も変えて継承されるよというものらしく。 これはいいですねえ。オブジェクト指向入門 ってこういう話もあるのかな。二分冊かよ!とか言ってないで読まないと。
'identity' return values とかいう議論を見ててちょっと面白いなあと思ったのでメモ。 関数の返値の型として、「引数をそのまま返す」と宣言できるとどうだろうかとかいう話。 元々「thisを返す」パターンはいろんなとこでよく使われてて、
class Stream {
Stream print(...) { ...; return this; }
}
(new HogeFugaStream).print(123)
.print("aaa")
.print("bbb");
こういうやつですね。昔っから議論の的になってるテーマでもあります。このパターンの問題は←で指摘されてるように、 メソッドの型宣言だけからはthisを返すのか別のStreamを返すのかがはっきりしないということと、
class HogeFugaStream {
HogeFugaStream printHoge() { return this; }
}
(new HogeFugaStream).print(123)
.printHoge(); ←エラー
サブクラスで増やしたメソッドを呼べないこと。カスケードすると部分式の型がわかりにくいっちゅーのは、 getterでもなくthisを返しもしないメソッドをカスケードすることってあんまりないと思うので 問題ないんじゃないかなあ。で、まあ、その前者2つが
class Stream {
this print(...) { ... }
}
こう書ければ解決するよね、という話。 あと、thisそのものを返すという情報は最適化に使えたりするので 多分そういう効果も。さらに、これ別にthisに限らなくても任意の引数について 「その引数そのものを返す」パターンはあるよね、と続いてるお話。
「サブクラスで増やしたメソッドを呼べない」は、元々ふつうに多相型がある言語だと問題なかったり
(例えばOCamlなら上のprintHogeは呼べるはず)、C++だと親クラスをテンプレートにしてCRTP
(class HogeStream : public Stream<HogeStream> { ... }
)という常套句が
確立されてますが、そういうのがあるにしても明示的に書けるのは便利だと思う。