20
abstract class Base{
      protected abstract void a();
}

class Child extends Base{
      @Override
      public void a(){
          //why is this valid
      }
}

可視性を下げることはできないが、増やすことはできるのはなぜですか?

また、表示されるパブリックメソッドが基本クラスのみであるテンプレートパターンを実装する必要があります。

例:

abstract class Base{
      public void callA(){
      //do some important stuff
      a();
      }

      protected abstract void a();
}

class Child extends Base{
      @Override
      public void a(){
          //why is this valid
      }
}

Javaで可視性を高めることができる場合、2つのメソッドが公開されていますか?

私はインターフェースが1つの解決策であることを知っていますが、他の方法がありますか?

4

4 に答える 4

28

可視性の低下が許可されない理由は、他の応答ですでに説明されています(親クラスの契約を破ることになります)。

しかし、なぜメソッドの可視性を高めることが許可されているのでしょうか。第一に、それはいかなる契約も破ることがないので、それを許可しない理由はありません。メソッドが保護されないことが子クラスで理にかなっている場合は、便利な場合があります。

次に、許可しないと、クラスの拡張とインターフェイスの実装を同時に実行できなくなるという副作用が発生する可能性があります。

interface Interface1 {
   public void method();
}

public class Parent {
   protected abstract void method();
}

public class Child extends Parent implements Interface1 {
   @Override
   public void method() {
   }
   //This would be impossible if the visibility of method() in class Parent could not be increased.
}

2番目の質問については、何もできません。子クラスを実装する人が、実装を妨げるようなことを何もしないことを信頼する必要があります。javaで可視性を高めることができない場合でも、抽象メソッドを呼び出す別の名前のパブリックメソッドを作成できるため、問題は解決しません。

class Child extends Base{
      @Override
      protected void a(){

      }

      public void a2() {
           a(); //This would have the same problems that allowing to increase the visibility.
      }
}
于 2012-10-08T11:54:13.593 に答える
13

基本クラスが可視性に関して約束をしている場合、サブクラスはその約束を破ることはできず、それでもリスコフの置換原則を満たします。約束が破られた場合、約束されたメソッドが公開される状況では、サブクラスを使用できません。

サブクラスIS-A基本クラス。基本クラスがメソッドを公開する場合、サブクラスも公開する必要があります。

JavaやC++で抜け出す方法はありません。同じことがC#にも当てはまると思います。

于 2012-10-08T11:30:25.990 に答える
5

可視性を下げることはできないが、増やすことはできるのはなぜですか?

視認性を低下させる可能性があると仮定します。次に、次のコードを見てください。

class Super {
    public void method() {
        // ...
    }
}

class Sub extends Super {
    @Override
    protected void method() {
        // ...
    }
}

これらのクラスを使用する別のクラスが別のパッケージにあるとします。

Super a = new Sub();

// Should this be allowed or not?
a.method();

メソッド呼び出しが許可されているかどうかを確認するために、コンパイラーはそれを呼び出す変数のタイプを調べます。変数のタイプaはですSuperaただし、参照する実際のオブジェクトはSubであり、メソッドはprotectedであるため、パッケージ外の無関係なクラスからメソッドを呼び出すことは許可されるべきではないと言えます。この奇妙な状況を解決するために、オーバーライドされたメソッドを目立たなくすることは禁止されています。

逆(メソッドをより見やすくする)では、同じ問題が発生しないことに注意してください。

于 2012-10-08T11:32:21.287 に答える
3

compile-timeJavaでは、スーパークラス参照がサブクラスオブジェクトを指すことができるため、制限をからに増やすことはできませんruntime

例を通してこれを見てみましょう:-

public class B {
    public void meth() {

    }
}

class A extends B {
    private void meth() {  // Decrease visibility.

    }
}

ここで、クラスのオブジェクトを作成し、Aそれにクラスの参照を割り当てBます。方法を見てみましょう。-

B obj = new A();  // Perfectly valid.

obj.meth();  // Compiler only checks the reference class..
             // Since meth() method is public in class B, Compiler allows this..
             // But at runtime JVM - Crashes..

さて、参照変数compilerの型だけをチェックし、そのクラス(クラスB)のメソッドの可視性をチェックし、 objがどのようなオブジェクトを参照しているかはチェックしないので、心配する必要はありません。それ..適切なメソッドを解決するのは実行時にJVMに任されています。reference

しかし、実行時に、オブジェクトはクラスAであるため、JVMは実際にクラスのメソッドを呼び出そmethうとしAます。しかし、今はどうなりますか... BooooOOMM --->JVMがクラッシュmethします。class A

そのため、視認性を低下させることはできません。

于 2012-10-08T11:33:52.213 に答える