メソッドをオーバーライドする派生クラスが、Java の基本クラスよりも制限的であってはならないのはなぜですか。コンパイラがエラーをスローするのはなぜですか?その理由を誰か説明してもらえますか?
4 に答える
要点は、スーパークラスについてしか知らない呼び出し元でも、指定されたサブクラスの任意のインスタンスを使用できる必要があるということです。次の状況を考慮してください。
public class Super
{
public void print()
{
System.out.println("Hello!");
}
}
public class Sub extends Super
{
@Override
void print() // Invalid
{
System.out.println("Package access");
}
}
別のパッケージから、次のものがあったと想像してください。
public void printSuper(Super x)
{
x.print();
}
そして、それを次のように呼び出しました:
printSuper(new Sub());
それが何をすることを期待しますか?メソッドをオーバーライドしているため、 「パッケージアクセス」と出力されるはずですが、それは別のパッケージからパッケージアクセスメソッドを呼び出していることを意味します...
基本的に、これはLiskov Substitution Principleの実行例の 1 つにすぎません。サブクラスの任意のインスタンスをスーパークラスのインスタンスとして扱えるようにする必要がありますが、それがサブクラスの制限をより厳しくすることにどのように適合するかを理解するのは困難です。
アクセス修飾子をさらに制限することはできません。これは、スーパークラス インスタンスの代わりにサブクラス インスタンスを置き換え可能にするという基本的な継承規則に違反するためです。
たとえば、Personクラスに多くのクラス (非サブクラスを含む) で使用されているgetName public メソッドがあるとします。しかし、誰かがEmployeeを Person のサブクラスとして追加したばかりで、Employee の getName は保護されており、サブクラスのみがアクセスする必要があります。以前のコードは壊れ始め、Employee は Person オブジェクトに置き換えられません。
したがって、Java はこの制限を課すことを決定しました。