• ベストアンサー

親クラスのメソッドを別のパッケージの子クラスでオーバーライドするときについて

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

  • Java
  • 回答数6
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • dekopa-
  • ベストアンサー率42% (161/378)
回答No.6

……できれば、質問し直す時は分けて下さいね。いつまでたっても収束しませんから。 質問1への回答  この場合、Mainと親クラスの関係だけが問題となります。  親クラスのメソッドfunc()を、別パッケージのMainがアクセスできるのは、前の私の回答を順に当てはめればpublicしか無い事に気づくはずです。  子クラスのオーバーライドの有無は関係ありません。Mainはインスタンスが親であれ子であれ、親クラスのクラス定義に従ってfunc()を読んでいるだけです。 質問2への回答  それが多態性というものです。Oya.foo()はあくまでOya.func()を読んでいるに過ぎません。それがabstractで、実は実態がないものだとか、そういうのは関係ありません。なぜなら、実際にfoo()がfunc()を呼び出している時点で、なんらかのインスタンスが生成されている筈で、そのインスタンス生成の条件はクラスやメソッドがabstractでない事だからです。  そうやって、「実態がある」と保証されたインスタンスのfunc()を呼んだ際には、オーバーライドによって実際のインスタンスを定義する子クラスkoのfunc()が呼び出されます。

takeshix100
質問者

お礼

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

その他の回答 (5)

  • dekopa-
  • ベストアンサー率42% (161/378)
回答No.5

指定無し : 同一パッケージからのみ参照出来る。制限付きのpublicみたいなモノ private : そのクラスでしか参照出来ない、もっとも範囲が狭い protected : privateに加えて、継承した子クラスからも参照出来る public : どのクラスからも参照出来る、公開された情報 通常、同一パッケージで継承したならprivate以外のどんな宣言でも見えます。 takeshix100の場合、それに「パッケージが違う」という条件が加わったので、protected, publicの2つに絞られた訳です。 オーバーライドするときも、単にメソッドを呼ぶ時も、「参照出来るか否か」という判断はこの4種類に絞られます。 #inner class等が絡むとまた混乱しますが、パッケージの指定と基本は同じですので。

takeshix100
質問者

補足

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(); } } ////////////////////////////////////////////////// 以上です。どうかご教授のほどよろしくお願いします。

  • nicepeace
  • ベストアンサー率58% (7/12)
回答No.4

しばらくJAVAから離れてるのであまり自信はないですが。 質問者様がどれくらいJAVAを理解しているのかにもよるのですが、今回のプログラムに限っての話しとしては。 abstractクラスを継承する場合には継承した方のクラスはabstractクラスに宣言されているメソッドをオーバーライドするか継承した方のクラスもabstract宣言をしなければエラーになります。 >オーバーライドされる親クラスのメソッド は、子クラスからアクセス可能なアクセス修飾子を 修飾しなければいけないということなのでしょうか? の質問ですが。 #2の時も書いたのでもう一度読んでみてください。 結論としてはだいたいその考えでokだと思います。 今回の話では違うパッケージでやっているわけですから違うパッケージからでもokなアクセス修飾子をつけなくてはいけないです。 アクセス修飾子というのはどこからアクセスできるか。 というのを設定しています。 もう一度書いてみます。 private・・・同じクラス内でのみ使用できる default・・・同じパッケージ内のすべてのアクセスok protected・・・同じパッケージ内、違うパッケージ内         そのサブクラスからアクセスok public・・・どこからでもok 違うパッケージ内の場合はdefaultとpraivateは違うパッケージでは呼び出せませんよね? 試しに同じパッケージにしてdefaultとprivateを試してみてください。 となると自然と答えが見えてくると思います。 #2とあわせてもう一度読んでみてください。

takeshix100
質問者

お礼

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

noname#18558
noname#18558
回答No.3

#1の方の言ってるのは嘘です。 逆だと思います。 実際にやってみれば歴然です。 で、質問の回答ですが。 Oyaクラスのfuncメソッドの修飾子はデフォルトなので、他のパッケージからは見えません。 なので、別パッケージであるkoクラスはfuncメソッドが見えません。 しかし、Oyaクラスのfuncメソッドを実装しないとならないのでエラーとなります。

takeshix100
質問者

補足

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

  • nicepeace
  • ベストアンサー率58% (7/12)
回答No.2

えっとそれはアクセス修飾子の話しですが。 private>default>protected>public でprivateのほうが強くなります。 No.1の方も書いてありますが、オーバーライドするときは親クラスのメソッドより子クラスのメソッドのアクセス修飾子を弱くするか同じにしなければいけません。 しかし、今回の問題はパッケージが違うということで privateは同じクラス内 defaultは同じパッケージ内 protectedは違うパッケージでもok publicはなんでもok と言う様に子クラスからアクセスできる範囲が決まっていますので、今回は違うパッケージなのでprotected以下の弱いアクセス修飾子を親クラスのメソッドに定義していなければ違うパッケージで子クラスのメソッドをオーバーライドすることはできまん。 多分こんな感じだと思います。

takeshix100
質問者

補足

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

回答No.1

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

takeshix100
質問者

補足

私の質問の仕方が本来の質問のしたかったこととは異なっ ていたようですので、改めて質問をさせていただきます。 例えば、以下のサンプルで、 ////////////////////////////////////////////////// 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であったとしても、コンパイル時に 「オーバーライドできません。」と警告されます。それは どうしてなのでしょうか改めてご教授のほどよろしく お願いします。

関連するQ&A

  • 【アクセス修飾子】アクセス修飾子無しのクラスにpublicなメソッド

    アクセス修飾子無しのクラスのメソッドにpublicを付ける意味がわかりません。 class MyClass {  public void method() {} } 例えばこのようなクラスがあったとします。 このクラスはアクセス修飾子無しで他のパッケージからはアクセス出来ない為、メソッドにpublicを付ける意味は無いと思うのですが、付けてもコンパイルは通ります。 何故なんだろう、と考えてみたのですが、例えばpublicなメソッドを持つpublicなクラスを継承し、そのメソッドをオーバーライドした時にメソッドにpublicを付けざるを得ない、あるいは、インターフェイス(暗黙的にメソッドにpublicが付く)を実装したときにメソッドにpublicを付けざるを得ない等、そういう場合に対応するための『遊び』みたいなものなのでしょうか? 御教授よろしくお願いします。

    • ベストアンサー
    • Java
  • 全パッケージの取得、全クラスの取得、全メソッドの取得

    やりたい事は、メインクラスより、同階層の全パッケージを取得(A)、 (A)より同階層の全クラスを取得(B)、 (B)より同階層の全メソッドを取得といったような事です。 例えば public class a { public static void main(String args[]) {  全パッケージの取得  全クラスの取得  全メソッドの取得 } } みたいな感じに。 試行錯誤したのですが、その処理を行う事の出来るメソッドかどうかも良く分からないし、 コンパイルエラーになるばかりで実現が出来ません。  ・メインクラスから同階層のパッケージを取得してパッケージ名を出力。  ・メインクラスからxパッケージ内の同階層のクラスを取得してクラス名を出力。  ・メインクラスからxパッケージにあるyクラス内のメソッドを取得してメソッド名を出力。 上記のようなめちゃくちゃシンプルなコードを挙げてご教示願います。

    • ベストアンサー
    • Java
  • 親クラスから子クラスへアクセス。

    親クラスから子クラスへアクセス。 お世話になります。 以下のプログラムについて考えています。 public class Main{  public static void main(String[] args) {   SubA subA = new SubA();   SubB subB = new SubB();   Super[] subs = {subA,subB};   subs[1].method();   subs[2].method();  } } class Super{  String str = "親";  public void method(){   System.out.println(str);  } } class SubA extends Super{  String str = "子A"; } class SubB extends Super{  String str = "子B"; } この場合、出力結果は当然 親 親 になります。 これを子クラスの str を表示するようにしたいのです。つまり 子A 子B です。 ただし、子クラスで method() をオーバーライドしたり、super.str = "子A" のように親クラスを書きかえずにです。 子クラスが何百種類もある場合、全く同じmethod()を書く無駄や、変更があったときにそれを全てを修正しなければならないことを避けたいのです。 何か良案がありましたら、ぜひご教授ください。よろしくお願いします。

  • 同一パッケージにあるクラスが見つからないエラー

    Tomcatとeclipseを用いてjspによるウェブアプリ開発の勉強をしているものです。 tagsrch.java内のメソッドに、同一パッケージ(フォルダ名:mangasearch)内のmangalist.javaで定義したmangaクラスというクラスを使いたいのですが、以下のように、シンボルが見つけられないというエラーが出てしまいます。 C:\(中略)\mangasearch>javac tagsrch.java tagsrch.java:11: エラー: シンボルを見つけられません public static List<manga> searchByKey(String k[]) throws IOException{ ^ シンボル: クラス manga 場所: クラス tagsrch tagsrch.java:14: エラー: シンボルを見つけられません manga[] list = new manga[cnum]; 同一パッケージ内に置かれている以上、tagsrch.javaにおいてmangaクラスが使えるはずだと思います。 ですが、いろいろなサイトを参考にして試してもmangaクラスが見つからないまま、tagsrch.javaがコンパイルできません。 初歩的質問で申し訳ありませんが、よろしくお願いいたします。 -参考- 1.いろいろ試したこと  1-1.カレントディレクトリを保存している場所より1つ上の場所でコンパイルする。  eclipseでtomcatプロジェクトを作成したため、どのクラスファイルにもpackage mangasearch;が含まれていました。なので1-1.を行い「javac パッケージ名/ファイル名」でコンパイルしてみました。  1-2.クラスパスを入れてコンパイルしてみる。  同一パッケージ内なので、この必要はないはずですが、  C:\(中略)\mangasearch>javac -classpath C:\(中略)\mangasearchでコンパイルしてみました。   下記のURLを参考にこの対策を講じましたが、エラーは変わりませんでした。  1-1.1-2.の参考URL:http://okwave.jp/qa/q2520327.html  1-3.メソッドをmangalist.java(mangaクラス)上で定義してしまう。  分割をあきらめ、tagsrch.java上のメソッドをmangalist.javaのmangaクラス上に定義してみました。 publicつけたままだと、 C:\(中略)\mangasearch>javac mangalist.java mangalist.java:76: エラー: クラスtagsrchはpublicであり、ファイルtagsrch.javaで宣 言する必要があります となったため、publicをとりました。するとコンパイルは出来ましたが、おそらく異なるパッケージからは使えないクラスとなったため、jsp上でアクセスできないというエラーが発生しました。 org.apache.jasper.JasperException: javax.servlet.ServletException: java.lang.IllegalAccessError: mangasearch/tagsrch このため、分割してtagsrch.javaを宣言する必要があり、1-3.の対策では最初にあげたmangaクラスを認識する問題に帰着すると思われます。 2.mangalist.java/tagsrch.javaについて mangalist.javaのコンパイルはできています。 mangalist.javaは、ただ単にmangaクラスとそれに付随するフィールド、コンストラクタを記述しただけのファイルです。 ■mangalist.java package mangasearch; class manga{ フィールド名 ・・・    manga(){    //コンストラクタ    } } ■tagsrch.java public class tagsrch extends manga{ メソッド{     } }

    • ベストアンサー
    • Java
  • クラス修飾子やアクセス修飾子を省略したパッケージ・プライベートは同じフォルダの下層フォルダにも公開するのですか?

     クラス修飾子やアクセス修飾子を省略したパッケージ・プライベートは同じフォルダの下層フォルダにも公開するのですか?  publicなどのクラス修飾子やアクセス修飾子を省略すると、同じフォルダ内のクラスにだけ公開されているパッケージ・プライベートなクラスなど(変数、メソッドとかのメンバを含む)になる、とのことですが、これは同じフォルダだけでなく同じフォルダの下層フォルダにも公開するのですか?  フォルダはパッケージのことです。 Windowsユーザーに分かりやすい言い方で記述しました。  よろしくお願いいたします。

    • ベストアンサー
    • Java
  • 親クラスとオーバーライドらへんのこと

    はじめまして、最近c++をはじめたものです。 質問があります。 サブクラスで親クラスのメソッドをオーバーライドした時に、 そのメソッドの中で親クラスのメソッド(オーバーライドした)をメソッドを呼び出したいのですが。 やりかたがわかりません。 要するに、javaでいうsuperを使いたいのですが。。 コードで書くとこんなかんじです。 class base { public: int abc(); } class derived : public base { public: int abc(); } int derived::abc() { super.abc() //←ここの部分がわかりません。 他の処理 }

  • アクセス修飾子

    アクセス修飾子 が理解できません。 ヘルプやインターネットで調べると下記のようにかかれています。 public 『アクセスの制限はありません。 』 protected 『アクセスは、コンテナ クラス、またはコンテナ クラスから派生した型に制限されます。 』 internal 『アクセスは現在のプロジェクトに制限されます。 』 protected internal 『アクセスは、現在のプロジェクト、またはコンテナ クラスから派生した型に制限されます。 』 private 『アクセスはコンテナ型に制限されます。』 public 、private は理解できるのですが、protected 、internal が理解できません。 Javaだとprotectedは同じパッケージ内、サブクラスでアクセス可能とかかれています。 .NETも同じでしょうか? 同じパッケージ内?ってどういうこと?となっています。 1つのオブジェクト内に2つのクラスを作成し、 クラスAのメソッドに protectedで作成し 、クラスBでクラスAの宣言をしたらAのprotectedのメソッドは使用できません。どういう場合にprotectedのメソッドは使用できるのでしょうか?

  • どのクラスのメソッドか、をどう見極めるか。

    どのクラスのメソッドか、をどう見極めるか。 Java初心者です(教科書で学んで、実践はこれからというレベル)。 参考書やネット上の資料等に掲載されているコードを見ていますと、 import文(10文くらい)で沢山のパッケージをimportしているようなクラスを しばしば目にしますが、このようなクラス内で使われている沢山のメソッドは、 それぞれ、どこかのクラスに属しているメソッドであるかと思います。 これらのメソッドについて、その仕様を知りたいと感じた場合、 それらがそれぞれ、どのクラスに属するのかを突き止める必要があるかと思いますが、 その突き止め方について、どなたか教えて下さい。 (一般的に普及している方法で結構です。) 例えば、知りたいと感じたメソッド名をネット検索し、 そのメソッドが「Javaの組み込みクラス」のメソッドである場合には、 ネット検索でヒットするでしょうから、その検索結果を受けて、 そのヒットしたクラスと、import文の内容とを比較し、 ネット検索でヒットしたクラスが、そのメソッドの格納主であると確信できれば、 それをもとに、そのメソッドの仕様を知ることができますよね。 (自作・他作のメソッドと、名前がバッティングしているかもしれないことを考慮すると、 やや頭が痛くなる問題になりませんか?) ネット検索で辿る方法が、まず頭に浮かびましたが、 これよりも効率的な方法がもし何かありましたら、教えて下さい。 ただ、一方で、 仕様を知りたいと思っているメソッドが、 「Javaの組み込みクラス」のメソッドではなく、 自作(もしくは、他作)のメソッドであった場合、 検索してもヒットはしませんから、その場合には、 import文にある自作もしくは他作のパッケージをしらみつぶしで探していくことになるのでしょうか? 当然、そのメソッドは、同一パッケージ内にあるクラスのpublicメソッドである可能性もありますから、 同一パッケージ内のクラスの中も、しらみつぶしに探していくことになりますよね? 各メソッドがコメントで「○○クラスのメソッド」というように注意書きされてあれば、 このような苦労はないのでしょうが、ネット上のソースを見る限りでは、 そんな親切なコメントはまず期待できないように思います。 以上、まとまりのない質問ではありますが、アドバイスを宜しくお願い致します。 自分のこの疑問が見当違いの疑問でしたら、その時は、ズバリそれを指摘して下さい。

    • ベストアンサー
    • Java
  • 子クラスのインスタンスから親クラスのインスタンス変数の内容を表示する親クラスのメソッドを叩きたい

    お世話になっております。 rubyのコーディングで疑問が発生しましたので、質問させてください。 以下の様にクラスを定義してあるとします クラスA 体裁を整えて標準出力するクラス  ・インスタンス変数@Aを持つ  ・@Aを元に整形して標準出力する振る舞いを持つ クラスB Aの子クラスで、標準出力する内容を細かく設定するクラス  ・独自のインスタンス変数は持たない  ・親クラスのインスタンス変数@Aを編集する振る舞いを持つ 上記の実装である時、クラスBの振る舞いでクラスAのインスタンス変数@Aを編集しようとした際にエラーが発生します。 尚、レシーバはsuperです。 エラー内容 ./clsb.rb:49:in `edt_dsp': super: no superclass method `edt_dsp' (NoMethodE rror) エラー文中に出てる'edt_dsp'というメソッドが親クラスのインスタンス変数を編集するメソッドです。 尚、子クラスには独自の変数は無いのでinitializeメソッドは定義していません。 なぜこのようなエラーが発生してしまうのかわからず困っています。 現在自分でも色々とサイトを回って調べていますが、解決には至っていません。 ご回答いただければ幸いです。 以上です。よろしくお願いします。

    • ベストアンサー
    • Ruby
  • オーバーライドしたメソッドで例外を投げたいとき

    お世話になります。 あるinterfaceを実装するクラスを作成しています。 そこでinterface内のメソッドを実装するわけですが、そこで例外を生成しthrowしたいと思っています。ですが、interfaceでそのメソッド定義にはその例外をthrowするようには定義されていないので、コンパイル時にエラーになります。 今は強引にNullPointerExceptionを生成するようなコードを書いて例外を発生させていますが、このようなケースではどのように記述するのが一般的なのでしょうか。 interfaceは内製ではないので変更することができません。 よろしくお願いいたします。

    • ベストアンサー
    • Java

専門家に質問してみよう