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

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

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

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

Q&A

解決済

2回答

2627閲覧

スタティックメソッドのオーバーライドについて

cre

総合スコア2

Java

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

0グッド

4クリップ

投稿2023/06/10 12:53

現在javaの学習中です。

「スタティックメソッドはオーバーライドできない」というルールがあるといくつかネットに書き込みがあったのですが、書籍には「staticメソッドやメンバ変数も再定義可能です。」と記載されています。
下記のコードは実行可能なのですが、スタティックメソッドにアノテーションを付けると
「staticメソッドは@Overrideで注釈付けすることはできません」
とコンパイルエラーになります。
なぜなのでしょうか?

class sample {
public static void main(String[] args){
sb s = new sb();
s.method();
}
}

class sp{
static public void method(){ System.out.println("sp-method"); }
}

class sb extends sp{
//@Override
static public void method(){ System.out.println("sb-method"); }
}

実行結果: sb-method

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

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

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

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

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

guest

回答2

0

ベストアンサー

再定義とかオーバーライドという言葉の使い方で混乱してるかな。一度公式ドキュメントを読んで整理しよう。

なんかのサイトで出てきてる”再定義”ってのは、「継承先で、おなじなまえで、"てーぎ"すること」という一般的な言葉に過ぎない。

一方、「オーバーライド」ってのはJavaのドキュメントに仕様みたいなもんとして定義されてる言葉。
https://docs.oracle.com/javase/specs/jls/se20/html/jls-8.html#jls-8.4.8.1

”再定義”っていう言葉と「オーバーライド」は同じではない。
語弊があるかもしれないが、”再定義”は「オーバーライド」を含むと考えたらわかりやすいかも。

で、もう一つの公式っぽい単語「隠蔽」っていう言葉を知ってるかどうか。
https://docs.oracle.com/javase/specs/jls/se20/html/jls-8.html#jls-8.4.8.2

スタティックメソッドは「オーバーライド」(override)できない。
言語仕様として「オーバーライド」できるのはインスタンスメソッドだけだ。
なので、@Overrideアノテーションをスタティックメソッドに使うとコンパイルエラーになる。

しかし、staticメソッドも、継承先で同じ名前をつかって再定義することはできる。
つまり「クラスを継承して、継承先で、継承元に存在するスタティックメソッドと同じ名前、同じ引数のスタティックメソッドを定義」することはできる。
この場合、継承元のスタティックメソッドは「隠蔽」される(hiding)。

形式上おんなじ、”メソッドの再定義”を行っているとしても、「オーバーライド」している場合と「隠蔽」が起こっている場合では、下記のような違いが出る。

  • オーバーライド:オーバーライドしたインスタンスメソッドによって、継承元のインスタンスメソッドが上書き(支配)される。オーバーライドされたインスタンスメソッドへのアクセスは、サブクラス内部からsuper()を使ってしかできなくなる。

  • 隠蔽:修飾名や、super、スーパークラス型へのキャストを含むメソッド呼び出し式を用いて元のメソッドにアクセスすることができる。

(なお、クラスメソッドでインスタンスメソッドを隠蔽しようとするとコンパイルエラーになる)

(わかりやすい例)
http://www.wisdomsoft.jp/123.html

まとめ

  • 形式上、スタティックメソッドを"再定義"することは可能 =インスタンスメソッドのオーバーライドの形式と同じように「クラスを継承して、継承先で、継承元に存在するメソッドと同じ名前、同じ引数のメソッドを定義」することはできる。(これは「オーバーライド」ではない。元のメソッドは「隠蔽」される)

  • 言語仕様として、スタティックメソッドを「オーバーライド」することはできなくされている。=スタティックメソッドに対して@overrideアノテーションを使うと、コンパイルエラーになる。

じゃあなんでそもそも、スタティックメソッドは「オーバーライド」できないの?

staticメソッドは、参照されるオブジェクトではなく参照の型に基づいて呼び出される=どのメソッドを呼び出すかが、コンパイル時に決定される。

「オーバーライド」は実行時の動的バインディングに依存するしくみになってるから、上記のようなstaticメソッドの仕様上、staticメソッドを「オーバーライド」することは原理的にできない。

(インスタンスメソッドはstaticメソッドと異なり、参照の型ではなく参照されてるオブジェクトの型に基づいて呼び出される=どのメソッドを呼び出すかが実行時に決定される)

投稿2023/06/10 14:04

編集2023/06/10 15:58
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

cre

2023/06/10 15:01 編集

> 言語仕様として「オーバーライド」できるのはインスタンスメソッドだけだ。 これ、知りませんでした。 java silver向けの紫の本で学習してたのですが、確かにスタティックメソッドに対して「再定義」とは書いていますが「オーバーライド」とは書いていないんですね。 でも、オーバーライドの説明項に記載してるし、最初に「オーバーライドとは、サブクラス内で、スーパークラスで定義しているメソッドと同じ名前でメソッドを再定義することです。」なんて書いてあるんですよ。罠ですよね。 何にせよ、スッキリしました。ありがとうございます。 ただもう一個気になるのが、質問で記載したコードでサブクラス(class sb)のmethodメソッドのpublicを外すと sample.java:13: エラー: sbのmethod()はspのmethod()をオーバーライドできません static void method(){ System.out.println("sb-method"); } (public)より弱いアクセス権限を割り当てようとしました と、コンパイルエラーが出ます。(Windowsのコマンドプロンプトでやってます) これは、再定義(隠蔽)の場合もオーバーライドの際のルールと同じく、スーパークラスの同名のメソッドより公開範囲を広げなければならないという事でいいですか? (オーバーライドで公開範囲を広げなければならない理由も現時点ではよくわかってないので、それを理解すればたぶん自ずと分かる部分なんだとは思いますが、そこはご容赦ください) また、「オーバーライドできません」のメッセージは、本来は「再定義できません」が正しいけど、そこまで細かくエラーメッセージのパターン分けをしてないからそういう表現が間違っている部分もあるってことなんでしょうか?
退会済みユーザー

退会済みユーザー

2023/06/11 02:05 編集

> ublicを外すと~コンパイルエラーが出ます。これは、再定義(隠蔽)の場合も~スーパークラスの同名のメソッドより公開範囲を広げなければならないという事でいいですか? 端的に言えば、Yes。 「クラスを継承して元のクラスの機能を拡張する」ための書き方って意味では、オーバーライドも隠蔽も、どちらも同じ。だから、機能拡張という役割をコントロールするという観点で、両者で同じエラーを出すこと自体は不自然ではない。 (staticメソッドをオーバーライドしようとするとエラーになるってのは、機能拡張云々ではなくて、実行時の動的バインディングという別の側面の話) >「オーバーライドできません」のメッセージは、本来は「再定義できません」が正しいけど、そこまで細かくエラーメッセージのパターン訳をしてないからそういう表現が間違っている部分もあるってことなんでしょうか? おそらくYES。 「override」っていうのは英語で「上書きする」っていう一般的な意味もあります。おそらく原文はその一般的な意味で使ってるのではないかと。それをそのままカタカナで訳しちゃったのが混乱の元。 Javaの言語仕様としてのoverrideとの区別を徹底するなら、ここは「再定義」とか「上書き」と訳したほうがよいでしょうね。 ---- >オーバーライドで公開範囲を広げなければならない理由(公開範囲を狭めてはいけない理由) リスコフの置換原則ってやつです。 「サブタイプは、スーパータイプを扱うのと同じように扱うことができなければならない」 仮に、サブクラス側でスーパークラスのアクセス権より制限を強くできるとした場合 例) class Superclass {  public void foo()   {    System.out.println("Superclass.foo");  } } class Subclass extends Superclass {  private void foo()   {    System.out.println("Subclass.foo");   } } これを Superclass a = new Subclass(); とすると、それまでSuperclass型のオブジェクトを受け取っていた関数にaを渡すと、エラーが発生する可能性があります。 (aが実装しているメソッドfooの可視性はprivateなので、aを受けとった関数が、a.foo()を実行した瞬間にエラーとなる) つまりSuperclassをSubclassで置換できません。 これは不都合なんで、サブタイプではスーパータイプよりアクセス制限を強くしてはならない、という仕様になっていると思われます。 https://stackoverflow.com/questions/17510152/why-cant-we-assign-weaker-privilege-in-subclass 上の例はクラスを継承した場合ですが、interfaceを実装してポリモルフィズムを行う場合を考えるとよりわかりやすいと思います。 (interfaceであらかじめ定義されている可視性よりも強い制限でimplementすることはできない)
cre

2023/06/10 16:49

リスコフの置換原則 初めて聞きました。 現在はとりあえず仕事の都合により資格取得優先で学習しているので「面白い < めんどくさい」になっているのですが、本当はこういう概念の部分のほうが面白いんだろうな・・・って感じです。 オーバーライド、再定義、隠蔽についてこの数時間で大変勉強になりました。 ありがとうございます。m(_ _)m
guest

0

再定義、ってのとオーバーライドはべつもんですよ

Javaのオーバーロードとは?オーバーライドとの違いや使い方をわかりやすく解説! | プログラミングを学ぶならトレノキャンプ(TRAINOCAMP)
https://camp.trainocate.co.jp/magazine/java-overload/

投稿2023/06/10 13:13

編集2023/06/10 13:15
y_waiwai

総合スコア87774

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

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

cre

2023/06/10 13:20

ありがとうございます。 記載いただいたURLに 「オーバーライド:継承元のクラスのメソッドを継承先のクラスで再定義すること」 とありますが・・・
y_waiwai

2023/06/10 13:30

あなたが実行可能として提示してるコードは再定義してますよねw
jimbe

2023/06/10 14:00 編集

つまり『「オーバーライド」は(全て)「再定義」』と言えますが『「再定義」は(全て)「オーバーライド」』とは限らないという感じでしょうか。
cre

2023/06/10 15:00

なるほど、オーバーライド = 再定義 だと完全に思っていました。
jimbe

2023/06/10 17:47 編集

オリジナルは英語なので用語/単語なのか表現なのか中途半端な翻訳で曖昧になっちゃうのも、分かり難い・間違え易い原因でしょうね。
Zuishin

2023/06/12 10:23

低評価があれば付けたいです。 再定義云々もリンク先を読まずに書いたのが明白ですが、なによりオーバーライドの質問にオーバーロードの説明を持ってくる意味不明さ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問