web-dev-qa-db-ja.com

メソッドをオーバーライドするとき、なぜアクセスを増やしても、減らさないのですか?

なぜJavaオーバーライドメソッドのアクセス指定子がオーバーライドメソッドよりも多くのアクセスを許可することを指定しますか?サブクラスではプライベートではありません。

60
yesilupper

これはOOPの基本原則です。子クラスは親クラスの完全なインスタンスであるため、親クラスとして少なくとも同じインターフェイスを提示する必要があります。保護されたものや公開されたものを見えにくくすることは、この考えに反するでしょう。子クラスを親クラスのインスタンスとして使用できないようにすることができます。

66
Patrick87

次の2つのクラスを想像してください。

public class Animal {
  public String getName() { return this.name; }
}

public class Lion extends Animal {
  private String getName() { return this.name; }
}

私はこのコードを書くことができます:

Animal lion = new Lion();
System.out.println( lion.getName() );

AnimalのメソッドgetName()はパブリックであり、Lionで非公開になっているため、有効でなければなりません。したがって、スーパークラス参照を取得すると、このようなものにアクセスできるようになるため、サブクラスで物事を見えにくくすることはできません。

33

以下の例をご覧ください

 class Person{
 public void display(){
      //some operation
    }
 }

class Employee extends Person{
   private void display(){
       //some operation
   }
 }

典型的なオーバーライドは、次の場合に発生します

Person p=new Employee();

ここで、pは、p.display()を呼び出しているときのPerson(super class)型のオブジェクト参照です。アクセス修飾子はより制限的であるため、オブジェクト参照pはアクセスできませんタイプEmployeeの子オブジェクト

9

奇妙だから:

class A {
    public void blah() {}
}

class B extends A {
    private void blah() {}
}


B b = new B();
A a = b;
b.blah();  // Can't do it!
a.blah();  // Can do it, even though it's the same object!
8

パーティーに遅れましたが、オーバーライドに関するもう1つの懸念を追加したいと思います。オーバーライドメソッドは、オーバーライドされたメソッドよりも少ない(または同じレベルの)スロー可能な例外を許可する必要があります。スロー可能なものもありません。

リスコフ置換原理もそれを説明できます:

interface Actionable {
  void action() throws DislocationException;
}

public class Actor implements Actionable {
  @Override 
  public void action() throws DislocationException {
     //....
  }
} 

public class Stuntman implements Actionable {
  @Override // this will cause compiler error
  public void action() throws DislocationException, DeathException {
     //....
  }
}

// legacy code to use Actionable
try {
   Actionable actor = new Actor(); // this cannot be replaced by a Stuntman, 
                                   // or it may break the try/catch block
   actor.action();
} catch (DislocationException exc) {
   // Do something else
}

上記で、オーバーライドされたメソッドは、最悪の場合、DislocationExceptionをスローするというコミットメントを行いました(撮影場所で医師が必要です)。そのため、オーバーライドメソッドは、DeathExceptionを追加することで(または救急車が必須)、それを壊してはなりません。

私はしばしば、「[より多くのアクセス] [レベル]、[しかし]より少ない例外」という優先ルールを呼び出します

4
U and me

サブクラスはスーパークラスの特殊化であるため、言い換えると、スーパークラスの拡張です。

たとえば、toStringメソッドを想像してください。すべてのJavaオブジェクトはクラスObjectを持っているため、オブジェクトを持っています。toStringprivateメソッドでクラスを定義できると想像してください。その後、すべてのオブジェクトを平等に扱うことはできなくなります。これを安全に行うことができます:

for (Object obj : collection) System.out.println(obj);

0
João Fernandes

さて、あなたが言及した特定のケースに関して、Javaそれをどのように正確に処理しますか?サブクラスがパブリック/保護されたメソッドをプライベートにした場合、そのメソッドが呼び出されたときにJVMは何をすべきですか?サブクラスのインスタンスですか?プライベートを尊重し、スーパークラスの実装を呼び出しますか?さらに、突然「コントラクトが最初に言ったことにも関わらず、このメソッドに誰もアクセスできない」と言うと、スーパークラスによって指定されたコントラクトを壊しています。

0
Marvo