Man is a Human? あるいはサブクラスと自由度
たまに,
class Human {} class Man extends Human {}
なんて書かれてるけど,これ,ほんとかな?
いや,たとえば,marryTo/1ってのは常識的に考えてHumanのメンバなわけだけど,
少なくとも多くの国では異性としか結婚できないわけで,結局,こうなる.
class Human {} class Man extends Human { Woman spouse; void marryTo(Woman woman) { spouse = woman; } } class Woman extends Human { Man spouse; void marryTo(Man man) { spouse = man; } }
そう,marryTo/1の実装が分散しちゃうんだ.
でも,これは決してHumanには実装できない.
class Human { Human spouse; void marryTo(Human human) { spouse = human; } } class Man extends Human { Woman spouse; @Override void marryTo(Woman woman) { spouse = woman; } } class Woman extends Human { Man spouse; @Override void marryTo(Man man) { spouse = man; } }
当然これはエラーだ.
継承ってのは自由度を増すことであって,こんなふうに自由度を減らすことはできない.
そしてこれはabstractを使っても同じ.
abstract class Human { abstract void marryTo(Human human); } class Man extends Human { Woman spouse; @Override void marryTo(Woman woman) { spouse = woman; } } class Woman extends Human { Man spouse; @Override void marryTo(Man man) { spouse = man; } }
そう,HumanにmarryTo/1を実装することはできないんだ.
この問題は結局,型システムにowl:disjointWithみたいな要素がないことが原因なんだけど,
これを実装しようとすると,たとえばこういうふうになる.
enum Sex { MALE, FEMALE }; class IllegalSexException extends Exception {} class Human { protected Sex sex; protected Human spouse; Human(Sex sx) { sex = sx; } Sex getSex() { return sex; } void marryTo(Human human) throws IllegalSexException { if (human.getSex() != sex) { spouse = human; } else { throw new IllegalSexException(); } } } class Man extends Human { Man() { super(Sex.MALE); } } class Woman extends Human { Woman() { super(Sex.FEMALE); } }
そう,システムの型システムを諦めて,自分で実装してしまう方法.
オントロジー的にはこれが一番正しいんだろうけど.なんせ不便.なんかExceptionとかはいてるし.
じゃあって,僕に考えつくのはこのぐらいなわけで.
interface Sex {} interface Male extends Sex {} interface Female extends Sex {} class Human <TSex extends Sex, TComplementarySex extends Sex> implements Sex { Human<TComplementarySex, TSex> spouse; void marryTo(Human<TComplementarySex, TSex> human) { spouse = human; } } class Man extends Human<Male, Female> implements Male {} class Woman extends Human<Female, Male> implements Female {}
これだとMaleとFemaleが相補的であることを誰も保証してくれないけど.
というか,なんか煩雑.
というわけで,困るわけです.どう書けばいいんだろう.
…あ,自由度の話書くの忘れた.