- PR -

オーバーライド時のアクセス権について

投稿者投稿内容
ヒデサク
会議室デビュー日: 2008/04/30
投稿数: 9
投稿日時: 2008-04-30 11:34
はじめまして。
クラスを継承しメソッドをオーバーライドした際の
アクセス権についての質問なのですが。

例)
class A{
public void methodA(){
}
}
class B extends A{
private void methodA(){ // オーバーライド
}
}

の様に親クラスのメソッドをオーバーライドする際、
なぜアクセス権を強くする方向にするとコンパイルエラーになるのでしょうか?
なにかその様にするとまずい理由があるのでしょうか。
それとも単なるJavaの仕様なのでしょうか。
どなたか教えて頂けないでしょうか。
宜しくお願いします
Edosson
ぬし
会議室デビュー日: 2004/04/30
投稿数: 675
投稿日時: 2008-04-30 11:58
継承しているくせに、親クラスに定義があるメソッドが使えないなんて、あり得ません。
そもそも、んなもんは継承じゃありません。

「何故エラーになるのか」を理解するためには、
オブジェクト指向を理解する必要があります。

継承を、コードの使い回しに便利な方法として利用するだけじゃなく、
これから、がんばってオブジェクト指向を勉強してください。

・・・ってだけじゃ何ですから。

メソッドの名称を具体的にすれば、わかりやすくなるかしらん。

コード:
// 動物だったら外見から足の数を数えることができますね。
class Animal {
  public getNumberOfFeet() {
    ...
  }
}

// この'Cat'は、外見から足の数を数えることができません・・・。
class Cat extends Animal {
  private getNumberOfFeet() {
    ...
  }
}

nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2008-04-30 16:09
よく継承はIs-a関係といいますが、子のクラスは親のクラスの機能を
完全に継承した上での拡張をしなければなりません。
親の機能を削ぐことはゆるされません。

親の機能をまるごと保有しているからこそ、親の型への代入が安全なのです。

先の例だと
コード:
A a = new B();
a.methodA();


とした場合、methodA()にはアクセスできるでしょうか、できないでしょうか?
ひろ@ya
大ベテラン
会議室デビュー日: 2006/02/23
投稿数: 168
投稿日時: 2008-05-02 12:05
代入の安全性を確保する必要が無いのなら、
B のインスタンス変数として A のインスタンスを保持するようにして、
アクセスできるようにしたいメソッドだけ明示して定義(処理は A に丸投げ)
する形になりますね。
コード:
public class B {

private A a = new A();
public void methodB() {
a.methodB();
}
//methodAは定義しないので外部からアクセス不可
}


どうしても継承した上で一部の機能を無効化したいなら、
コード:
public class B extends A {

public void methodA() {}
}


とか、
コード:
public class B extends A {

public void methodA() {
throw new UnsupportedOperationException();
}
}


でしょう。


[ メッセージ編集済み 編集者: ひろ@ya 編集日時 2008-05-02 12:11 ]
indigo-x
大ベテラン
会議室デビュー日: 2008/02/21
投稿数: 207
お住まい・勤務地: 太陽の塔近く
投稿日時: 2008-05-02 13:47
Javaの仕様ですね。
C++ならもう少し柔軟な事ができます。
ヒデサク
会議室デビュー日: 2008/04/30
投稿数: 9
投稿日時: 2008-05-02 15:10
Edossonさん nagiseさん ひろ@yaさん indigo-xさん
返事ありがとうございます。

>nagiseさん
>よく継承はIs-a関係といいますが、子のクラスは親のクラスの機能を
>完全に継承した上での拡張をしなければなりません。
>親の機能を削ぐことはゆるされません。
この説明を受け、extendを辞書で調べてみましたが、
広げる、拡張する、など大きくする意味である事が分かりました。
すると、僕の質問した継承してアクセス権を狭めると言うのは
矛盾している事だと分かりました。


>Edossonさん
>継承を、コードの使い回しに便利な方法として利用するだけじゃなく、
>これから、がんばってオブジェクト指向を勉強してください。
まだオブジェクト指向に振り回されている自分ですが、
この文章を読んで何かハッと気付くものがありました。
もっと勉強してオブジェクト指向を使いこなせる様にがんばります。

ヒデサク
会議室デビュー日: 2008/04/30
投稿数: 9
投稿日時: 2008-05-02 15:19
<追加>
もし、継承した上で一部機能を無効化したい場合は
ひろ@yaさんのおっしゃる通り、
継承側で『このメソッドは使えませんよ』など、
無効化している事を返すのがベストのようですね。

皆さんのおかげですっきりと納得する事が出来ました。
本当にありがとうございました。
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2008-05-02 15:28
javaの継承はLiskovの置換原則に則っています。
従って、アクセス権を強化することは、親クラスで認められている操作が子クラスで認められなくなるため、だめなのです。

...と、書いてる途中で、スレ主、スレッド終わらせちゃった。(´・ω・`)

スキルアップ/キャリアアップ(JOB@IT)