質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

962閲覧

Java:インターフェースを実装した子クラスを基に生成したインスタンスから、インターフェースで宣言したstaticメソッドへのアクセスができない理由

karakorum

総合スコア20

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

2グッド

0クリップ

投稿2020/11/07 09:07

#質問概要
下記ソースコードを基に質問させていただきます。
ソースコードの5行目では、子クラスを基に生成したインスタンスから、親クラス(抽象クラス)のstaticなメソッドにアクセスができています。この部分は理解しています。
しかし、7行目では子クラスを基に生成したインスタンスから、実装したインターフェースのstaticなメソッドにアクセスできません。なぜでしょうか?
恐らく、私の抽象クラスとインターフェースの理解が浅いことが原因だと考えられるので、抜けている知識を補強していただきたです。

#ソースコード

package test; public class Sub extends AbstSample implements InterSample{ public static void main(String[] args) { Sub absub=new Sub(); absub.abstMethod(); Sub insub=new Sub(); insub.interMethod(); } } abstract interface InterSample{ public static void interMethod() { System.out.println("インターフェース"); } } abstract class AbstSample{ public static void abstMethod() { System.out.println("抽象クラス"); } }

上記ソースコードをコンパイルすると、
5行目で警告文、
「型 AbstSample からの static メソッド abstMethod() には static にアクセスする必要があります」が出てきます。
また、7行目でコンパイルエラーが起こります。
「メソッド interMethod() は型 Sub で未定義です」

#備考①
「そもそも、親クラスのstaticなメンバを子クラスを基に生成したインスタンスからアクセスしよとすること自体がおかしい!というか、そんな場面あるわけない。」ということは理解しています。
しかし、Java言語では機能上これができます。質問としてはその部分ではなく、なぜ、5行目できていることが、7行目ではできないのか、という疑問にもしご回答できる方がいたら、教えていただきたいです。宜しくお願い致します。

q_sane_q, ozwk👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

interfaceにstaticなメソッドを持たせる書き方は確かJava8? から実装されたのですが、
そのstaticメソッドはそのinterfaceが持っているものであってそのinterfaceから呼び出して使用するものです。

Java

1InterSample.interMethod();

そしてこのstaticメソッドは、そのinterfaceを実装したclassには受け継がれません。
なのでSubはinterMethod()を持っておらず、エラーとなります。

警告は見た通りの、staticメソッドをインスタンスから呼ぼうとしたときに発生するいつものやつです。

投稿2020/11/07 09:26

q_sane_q

総合スコア610

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

karakorum

2020/11/07 09:59

ご回答いただきありがとうございます。 具象クラスや抽象クラスを継承する場合、(アクセス修飾子にもよりますが)すべてのメンバが子クラスに継承されるため、警告が出てくるもののインスタンスからstaticメンバにアクセスができる。 しかし、インターフェースの場合、子クラスに実装されるメンバの中にstaticメソッドは含まれていない、つまり子クラスには存在しないことになる。なので、子クラスのインスタンスからインターフェースで宣言しているstaticなメソッドにアクセスすることができない、という解釈であっているでしょうか? もしそうであれば、納得しました。ありがとうございます。
karakorum

2020/11/07 10:05

深堀りになるのですが、 「インターフェースのstaticメソッドは、そのインターフェースを実装したclassには受け継がれない」 これはなぜだと思いますか? 「Javaの機能上そうなっているから」と言われたらそれまでなのですが、もし考えを持っているのだとしたら、主観でもいいので、お聞きしたいです。 よろしくお願いします。
q_sane_q

2020/11/07 10:25

extendsとimplementsは似てるように見えて別の概念です extendsは親クラスに機能を追加して拡張(extend)した子クラスを作る行為で、「親クラス+子クラス追加分」なので親クラスのものは受け継がれます 親クラスと子クラスはそのように親子的関係にあることが良い設計とされます 一方implementsは「実装」と言われますが「そのクラスではimplementsしたinterfaceで定義されているメソッドが存在している(実装しないとコンパイルエラーになるから)」ということを示すマークのようなもので親から子に何かが受け継がれるような概念ではありません。 それぞれ親子関係になっている必要もなく、 例えば「java.lang.Comparable」というinterfaceはjava.util.Dateクラスにもjava.io.Fileクラスにも実装されていて「compareTo」というメソッドが存在することを保証しています 元々、昔はinterfaceに書かれるメソッドというのは名前や引数、戻り値の型などが定義されるだけで、中身の実装(受け継ぐようなもの)は書けませんでした Java8でいろいろあって、static、defaultなどがinterfaceに現れ、メソッドの実装を書けるようになり、結果として抽象クラスとの差が少なくなり「抽象クラスっぽいもの」に近づきました。 が、元々のinterfaceの在り方が何かを受け継がせるものではなかったため、今でもimplementsで実装したクラスに何かを受け継がせることは極力しないような(defaultなんかは受け継がれますが)設計になっています。 ……というのが私の考えです。Javaの中の人ではないので真意はわからないんですが。
q_sane_q

2020/11/07 10:30

defaultも「受け継がれる」というより、「implements(実装)」のニュアンスに沿って「取り付けられる」と言った方が近いかもしれないです。
karakorum

2020/11/07 11:09

Javaのバージョンが進むにつれ、インターフェースが抽象クラスのような何かに近づいていってしまったが、本来の意図としてはメソッドの存在を示すマークのようなものである。そしてその本来の意図を汲み取ると、実装クラスに何かを受け継がせることは、あまりしたくない、ということですね。 確かに真意は分からないにしても、 私個人としては、とても納得しました。 ありがとうございました!
q_sane_q

2020/11/07 11:22 編集

実際は「受け継がせることはしたくない」というより「お互い全く関係ないクラスにメソッド定義を貼り付ける」という使い方上、「それらに共通した処理くっつけてすべてのクラスで使用することある? ないでしょ? そうしたいときだけdefaultにしてね」という感じなのかもしれませんね。
karakorum

2020/11/07 11:46 編集

「それらに共通した処理くっつけてすべてのクラスで使用することある? ないでしょ? そうしたいときだけdefaultにしてね」 すいません、ここの部分が良くわかりませんでした・・・ 私が読み取った解釈としては、 「インターフェースで処理まで定義したメソッドをクラスに実装する際、共通した処理として定義(staticなメソッド)したい時なんてないよね?もし処理まで定義したメソッドを実装したいなら、defaultにしてね。」 ということでしょうか? 一つ疑問なのですが、インターフェースに処理まで定義したメソッドを宣言し、クラスに実装するなら、staticなメソッドでもdafaultなメソッドでも、どっちでも良いのでは?と感じてしまいました・・・。 現在のJavaの機能上、インターフェースで宣言されたstaticなメソッドは、実装したクラスでは参照できません。なので、インターフェースで処理まで定義したメソッドを実装したクラスでも扱いたい場合は、dafaultメソッドを使うべきです。 しかし、「なぜstaicなメソッドが実装先クラスでは参照できないのか」というそもそもの話に戻ると、「インターフェースで処理まで定義したメソッドを実装先クラスでも扱いたいときは、staticなメソッドを使ってね。実装先クラスでも参照できるようにしておくから!」「そうなるとdefaultメソッドの意味がなくなるから、この機能はいらないか」みたいにはならないですかね?
q_sane_q

2020/11/07 11:56

たとえばjava.lang.Comparableはjava.util.Dateとjava.io.Fileと他にもいろいろなクラスにimplementsされてますがそれら全てで使われる共通の処理は多分そうそうないので、実装した処理全てを各クラスに撒く必要はないと考えられてるんじゃないかと思う……ということです。 あとstaticメソッドはnewしたインスタンスで使うべきものではないです。各インスタンスが持っているフィールドにも干渉できません。なのでstaticメソッドはdefaultのかわりにはならないです。
karakorum

2020/11/07 12:18

理解できました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問