プロが教えるわが家の防犯対策術!

早速ではございますが、質問をさせていただきます。
親クラスのパッケージとは異なるパッケージに子クラスが
あるとき、子クラスが親クラスのメソッドをオーバーライ
ドするときに、親クラスのメソッドのアクセス修飾子を
publicかprotectedにしなければコンパイルエラーになり
ます。それはなぜなのでしょうか?
どうかご教授のほどよろしくお願いします。

A 回答 (6件)

……できれば、質問し直す時は分けて下さいね。

いつまでたっても収束しませんから。


質問1への回答
 この場合、Mainと親クラスの関係だけが問題となります。
 親クラスのメソッドfunc()を、別パッケージのMainがアクセスできるのは、前の私の回答を順に当てはめればpublicしか無い事に気づくはずです。
 子クラスのオーバーライドの有無は関係ありません。Mainはインスタンスが親であれ子であれ、親クラスのクラス定義に従ってfunc()を読んでいるだけです。

質問2への回答
 それが多態性というものです。Oya.foo()はあくまでOya.func()を読んでいるに過ぎません。それがabstractで、実は実態がないものだとか、そういうのは関係ありません。なぜなら、実際にfoo()がfunc()を呼び出している時点で、なんらかのインスタンスが生成されている筈で、そのインスタンス生成の条件はクラスやメソッドがabstractでない事だからです。
 そうやって、「実態がある」と保証されたインスタンスのfunc()を呼んだ際には、オーバーライドによって実際のインスタンスを定義する子クラスkoのfunc()が呼び出されます。
    • good
    • 0
この回答へのお礼

dekopa-様へ
ご回答ありがとうございました。
とても勉強になりました。

お礼日時:2006/03/21 22:40

指定無し : 同一パッケージからのみ参照出来る。

制限付きのpublicみたいなモノ
private : そのクラスでしか参照出来ない、もっとも範囲が狭い
protected : privateに加えて、継承した子クラスからも参照出来る
public : どのクラスからも参照出来る、公開された情報

通常、同一パッケージで継承したならprivate以外のどんな宣言でも見えます。
takeshix100の場合、それに「パッケージが違う」という条件が加わったので、protected, publicの2つに絞られた訳です。

オーバーライドするときも、単にメソッドを呼ぶ時も、「参照出来るか否か」という判断はこの4種類に絞られます。

#inner class等が絡むとまた混乱しますが、パッケージの指定と基本は同じですので。

この回答への補足

dekopa-様へ
ご回答ありがとうございました。私の本当に知りたいこと
が質問内容にうまく反映されていませんでしたので、改め
て質問をさせていただきます。質問が2つございます。

質問1 メソッドのオーバーライドについてのことなので
    すが、親クラスと子クラスはともに異なるパッケ
    ージの中にあるとき、パッケージの外にある
    Mainクラス(mainメソッドのあるクラス)で、子ク
    ラスをnewした値を親クラスの参照変数に代入し
    て、その参照変数で子クラスでオーバーライドし
    ているメソッドを呼出したとき、親クラスのオー
    バーライドされたメソッドは、Mainクラスから見    えるようにpublicにしなければならないのはなぜ    なのか。
    
質問2 以下のコードで、Oyaクラスのfooメソッド内で
    funcメソッドを呼び出すとき、OyaクラスからKoク
    ラスのprotectedなメソッドをなぜ呼び出すことが
    できるのか。
//////////////////////////////////////////////////
package ko;

import oya.Oya;

public final class Ko extends Oya
{
protected void func()
{
System.out.println("func");
}
}
//////////////////////////////////////////////////
package oya;

public abstract class Oya
{
protected abstract void func();

public final void foo()
{
this.func();
}
}
//////////////////////////////////////////////////
import oya.Oya;
import ko.Ko;

final class Main
{
public static void main(String[] args)
{
Oya oya = new Ko();
oya.foo();
}
}
//////////////////////////////////////////////////
以上です。どうかご教授のほどよろしくお願いします。

補足日時:2006/03/21 14:32
    • good
    • 0

しばらくJAVAから離れてるのであまり自信はないですが。


質問者様がどれくらいJAVAを理解しているのかにもよるのですが、今回のプログラムに限っての話しとしては。

abstractクラスを継承する場合には継承した方のクラスはabstractクラスに宣言されているメソッドをオーバーライドするか継承した方のクラスもabstract宣言をしなければエラーになります。


>オーバーライドされる親クラスのメソッド
は、子クラスからアクセス可能なアクセス修飾子を
修飾しなければいけないということなのでしょうか?

の質問ですが。
#2の時も書いたのでもう一度読んでみてください。
結論としてはだいたいその考えでokだと思います。

今回の話では違うパッケージでやっているわけですから違うパッケージからでもokなアクセス修飾子をつけなくてはいけないです。

アクセス修飾子というのはどこからアクセスできるか。
というのを設定しています。

もう一度書いてみます。

private・・・同じクラス内でのみ使用できる
default・・・同じパッケージ内のすべてのアクセスok
protected・・・同じパッケージ内、違うパッケージ内
        そのサブクラスからアクセスok
public・・・どこからでもok

違うパッケージ内の場合はdefaultとpraivateは違うパッケージでは呼び出せませんよね?
試しに同じパッケージにしてdefaultとprivateを試してみてください。
となると自然と答えが見えてくると思います。
#2とあわせてもう一度読んでみてください。
    • good
    • 0
この回答へのお礼

nicepeace様へ
大変勉強になりました。ご教授ありがとうございました。
ご回答を再度繰り返して読み勉強したいと思います。

お礼日時:2006/03/20 20:29

#1の方の言ってるのは嘘です。


逆だと思います。
実際にやってみれば歴然です。

で、質問の回答ですが。
Oyaクラスのfuncメソッドの修飾子はデフォルトなので、他のパッケージからは見えません。
なので、別パッケージであるkoクラスはfuncメソッドが見えません。
しかし、Oyaクラスのfuncメソッドを実装しないとならないのでエラーとなります。

この回答への補足

DQ9様へ
 ご回答ありがとうございます。D9様へ質問がございま
す。Oyaクラスのメソッドが別パッケージのKoクラスで
オーバーライドされるためには、Oyaクラスのメソッドが
Koクラスから見えるようにアクセス修飾子を修飾しなけれ
ばいけないということでよろしいのでしょうか?

補足日時:2006/03/20 19:18
    • good
    • 0

えっとそれはアクセス修飾子の話しですが。



private>default>protected>public

でprivateのほうが強くなります。

No.1の方も書いてありますが、オーバーライドするときは親クラスのメソッドより子クラスのメソッドのアクセス修飾子を弱くするか同じにしなければいけません。

しかし、今回の問題はパッケージが違うということで
privateは同じクラス内
defaultは同じパッケージ内
protectedは違うパッケージでもok
publicはなんでもok
と言う様に子クラスからアクセスできる範囲が決まっていますので、今回は違うパッケージなのでprotected以下の弱いアクセス修飾子を親クラスのメソッドに定義していなければ違うパッケージで子クラスのメソッドをオーバーライドすることはできまん。

多分こんな感じだと思います。

この回答への補足

改めて質問をさせていただきます。
「子クラスからアクセスできる・・・・」
ということは、オーバーライドされる親クラスのメソッド
は、子クラスからアクセス可能なアクセス修飾子を
修飾しなければいけないということなのでしょうか?
どうかご教授のほどよろしくお願いします。

補足日時:2006/03/20 17:27
    • good
    • 0

メソッドをオーバーライドするときは、そのスコープが広い方向へアクセス修飾子を付け直すことはできません。



例えば、親クラスのメソッドがprotectedだった場合、子クラスでオーバーライドする際にprotectedやprivateにはできますがpublicにはできません。
スコープの範囲は、
public > protected > default(修飾子なし) > private
です。
子クラスのアクセス修飾子を確認してみてください。

この回答への補足

私の質問の仕方が本来の質問のしたかったこととは異なっ
ていたようですので、改めて質問をさせていただきます。
例えば、以下のサンプルで、
//////////////////////////////////////////////////
package oya;

public abstract class Oya
{
abstract void func();
}
//////////////////////////////////////////////////
package ko;

import oya.Oya;

public final class Ko extends Oya
{
public void func()
{
System.out.println("func");
}
}
//////////////////////////////////////////////////
import ko.Ko;

final class Main
{
public static void main(String[] args)
{
Ko obj = new Ko();
obj.func();
}
}
//////////////////////////////////////////////////
Oyaクラスの抽象メソッドのアクセス修飾子がデフォルト
であった場合にたとえKoクラスのオーバーライドしたメソ
ッドがpublicであったとしても、コンパイル時に
「オーバーライドできません。」と警告されます。それは
どうしてなのでしょうか改めてご教授のほどよろしく
お願いします。

補足日時:2006/03/20 17:10
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!