public class Food {
private String name;
Food(String f) { name = f; }
public static void main(String args[]) {
Person p = new Person();
Vegetarian v = new Vegetarian();
Vegetable v1 = new Vegetable("Cabbage");
Food f1 = new Food("Meat");
System.out.println(
"Can a person eat cabbages? "+p.Eat(v1));
System.out.println(
"Can a person eat meats? "+p.Eat(f1));
System.out.println(
"Can a vegetarian eat cabbages? "+
v.Eat(v1));
System.out.println(
"Can a vegetarian eat meats? "+v.Eat(f1));
}
}
class Vegetable extends Food {
String name;
Vegetable(String s) { super(s); name = s; }
}
class Person {
public boolean Eat(Food f) { return true; }
}
class Vegetarian extends Person {
public boolean Eat(Vegetable v){return true;}
}
Can a person eat cabbages? true Can a person eat meats? true Can a vegetarian eat cabbages? true Can a vegetarian eat meats? trueこのように「菜食主義者」(vegetarian) が,「肉を食べることが出来てしま う」(最後の行) が問題である.この原因として,「菜食主義者」は,「人間」の サブクラスであるので, Eat(Vegetable v) に当てはまらない場合は, 人間の Eat(Food f) を継承してしまうためである. そもそも,「菜食主義者」は,「人間」のほとんどの性質を継承するが, 「野菜以外の食べ物は食べない」ことを表現するために,オーバーライドを利 用するが,うまく表現できない.
では,例えば,
class Vegetarian {
public boolean Eat(Vegetable v){return true;}
}
一般に,このような時は(Java では書けないが), TypeOperator を使う ことが知られている.結果として,人間と菜食主義者のサブタイプ関係は成り 立つ.
TypeOperator Person[F<:Food] {
public boolean Eat(F f) { return false; }
}
TypeOperator Vegetarian[V<:Vegetable] {
public boolean Eat(V v) { return ture; }
}
結果として
であるが,逆は成立しない関係である.ここで,クラス
,
のインスタン スを
,
とし,更に,その型を
,
と書く.
の型が
の型のサブタイプである時
とする.