2011年10月23日日曜日

オーバーライド時のアクセス修飾子変更 Java 編

PHP 編 に続き、今度は Java で検証。

まず、親クラス。
class ParentClass
{
  private void func1() { System.out.println("Parent private func1"); }
  protected void func2() { System.out.println("Parent protected func2"); }
  public void func3() { System.out.println("Parent public func3"); }

  public void call()
  {
    this.func1();
    this.func2();
    this.func3();
  }
}
private, protected, public の 3 種類のメソッドと、それらを呼び出すメソッドを作成。

子クラス1 は public に変更。
class Child1Class extends ParentClass
{
  // メソッドはスーパータイプのメソッドをオーバーライドまたは実装しません
  // @Override
  public void func1() { System.out.println("Child1 private -> public func1"); }
  @Override
  public void func2() { System.out.println("Child1 protected -> public func2"); }
  @Override
  public void func3() { System.out.println("Child1 public func3"); }
}
func1 は private メソッドをオーバーライド出来ないため、コンパイルエラーとなる。
@Override アノテーションを外すと、コンパイルは通る。

子クラス2 は protected に変更。
class Child2Class extends ParentClass
{
  // メソッドはスーパータイプのメソッドをオーバーライドまたは実装しません
  // @Override
  protected void func1() { System.out.println("Child2 private -> protected func1"); }
  @Override
  protected void func2() { System.out.println("Child2 protected func2"); }
  // Child2Class の func3() は ParentClass の func3() をオーバーライドできません。スーパークラスでの定義(public) より弱いアクセス特権を割り当てようとしました。
  // @Override
  // protected void func3() { System.out.println("Child2 public -> protected func3"); }
}
func1 は同じようにエラー。
func3 は PHP と同じように、public -> private への変更でエラーとなる。func1 とは異なり、アノテーションを外しただけではエラー。定義自体を削除。

子クラス3 は private に変更。
aclass Child3Class extends ParentClass
{
  // メソッドはスーパータイプのメソッドをオーバーライドまたは実装しません
  // @Override
  private void func1() { System.out.println("Child3 private func1"); }
  // Child3Class の func2() は ParentClass の func2() をオーバーライドできません。スーパークラスでの定義(protected) より弱いアクセス特権を割り当てようとしました。
  // @Override
  // private void func2() { System.out.println("Child3 protected -> private func2"); }
  // Child3Class の func3() は ParentClass の func3() をオーバーライドできません。スーパークラスでの定義(public) より弱いアクセス特権を割り当てようとしました。
  // @Override
  // private void func3() { System.out.println("Child3 public -> private func3"); }
}

func1 は同じようにエラー。
func2, func3 でエラーとなる。やはり、厳しい方向への変更はできないようだ。

実行してみると、
ParentClass p = new ParentClass();
p.call();
System.out.println("----------");
Child1Class c1 = new Child1Class();
c1.call();
System.out.println("----------");
Child2Class c2 = new Child2Class();
c2.call();
System.out.println("----------");
Child3Class c3 = new Child3Class();
c3.call();

結果は、
Parent private func1
Parent protected func2
Parent public func3
----------
Parent private func1
Child1 protected -> public func2
Child1 public func3
----------
Parent private func1
Child2 protected func2
Parent public func3
----------
Parent private func1
Parent protected func2
Parent public func3

エラー部分を削除したソース、結果共に、PHP と同じようになった。

protected -> public への変更はできるが、public -> protected -> private への変更はできない。
private はオーバーライドできない。

余談だが、コンパイルエラーとなるのはやはりいい。

0 件のコメント:

コメントを投稿