- PR -

interface のメソッドは、なぜ protected にできないのでしょうか?

投稿者投稿内容
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-07-11 15:56
unibon です。こんにちわ。

その後、Java Language Specification Second Edition
http://java.sun.com/docs/books/jls/second_edition/html/interfaces.doc.html
をチラッと見てみたのですが、
なぜメソッドが public だけなのかは理由が分かりませんでした。

とても とても とても とても恐れ多いのですが、言語仕様を作った人々、
http://java.sun.com/docs/books/jls/second_edition/html/j.title.doc.html
が、public 以外がありうることをついウッカリ忘れてしまっていた、
という、ただそれだけ、のような気がしてなりません。
#たとえ、万が一そうだったとしても、責めているわけではありませんので。

昔は、内部クラスの仕組みもなかったので、気づかなかったのでしょう。
#と、もう、決め付けてしまっていますが。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2003-07-11 16:29
unibonさんの書き込み (2003-07-11 15:56) より:
>とても とても とても とても恐れ多いのですが、言語仕様を作った人々、
http://java.sun.com/docs/books/jls/second_edition/html/j.title.doc.html
が、public 以外がありうることをついウッカリ忘れてしまっていた、
という、ただそれだけ、のような気がしてなりません。

他の方も触れていますが、interfaceはオブジェクトの外部仕様を規定するためのもの
なので、publicしかなくて当然だと思うのですが。そもそもの目的と違う用途に使えない
かたと言って言語仕様をどうこういうのはおかしくないですか?
お犬様
ベテラン
会議室デビュー日: 2003/01/26
投稿数: 67
投稿日時: 2003-07-11 18:30
引用:
ukさんの書き込み (2003-07-11 16:29) より:

他の方も触れていますが、interfaceはオブジェクトの外部仕様を規定するためのものなので、publicしかなくて当然だと思うのですが。



私も そう思うのですが、
それだと思考停止しているような気もするので理由を無理やり考えてみました。
1.このようなアクセス制限が必要な事は比較的少ないので却下された。
2.このようなアクセスを制限をしたい、という要求を聞いていると
 アクセス修飾子が幾つあっても足りない。例えば
 class A {
  //ここには書かないけど method は class B からだけ利用されるメソッドとする。
  void method(){}
  public static void main(String[] args){
   A a = new A();
   a.method(); //これをコンパイルエラーにしたい。
   B b = new B();
   b.someMethod( a ); //この中で method が呼ばれる。これが method の本来の使い方。
  }
 }
 というような無茶な要求があっても普通は却下しますよね。

基本的には interface は「それを実装するクラス」や
「実装クラスと同パッケージのクラス」のために存在するのでは無く、
「その interface を利用するクラス」のためにある。
そして、「その interface を利用するクラス」のパッケージを限定しないとすれば、
public しか指定できないのは当然の話なのだと思われます。

[ メッセージ編集済み 編集者: お犬様 編集日時 2003-07-11 21:09 ]
Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2003-07-11 19:09
どうも、Wataです。
引用:

ukさんの書き込み (2003-07-11 16:29) より:
他の方も触れていますが、interfaceはオブジェクトの外部仕様を規定するためのものなので、publicしかなくて当然だと思うのですが。


引用:

お犬様さんの書き込み (2003-07-11 18:30) より:
基本的には interface は「それを実装するクラス」や「実装クラスと同パッケージのクラス」のために存在するのでは無く、「その interface を利用するクラス」のためにある。
そして、「その interface を利用するクラス」のパッケージを限定しないとすれば、 public しか指定できないのは当然の話なだと思われます。


publicなインターフェースに限定指定言えば当然だと思いますし、お犬様の書き込みは非常に的を得ていると思います。

しかし、パッケージプライベート(無指定)やメンバ型としてのprivateやprotectedのインターフェイスの存在を考えると少し不便な気がします。

仮にパッケージプライベートのインターフェイスで詳細実装にかかわる(いつ変更されるかわからない)部分の型を定義したいと思います。すると、インターフェイスのメソッドはpublicにしなければならないので詳細実装のはずが、インターフェイスを実装するpublicクラスは実装メソッドをpublicにして外部にさらさなければならなくなります。そうすると、もはや後日の実装の変更は不可能になります。

こう考えると、インターフェイスのメソッドもインターフェイスと同じかそれよりも上のアクセス指定でもよいような気がします。
(つまりパッケージプライベートなインターフェイスはパッケージプライベートなメソッド、privateなインターフェイスはprivateなメソッドを定義できるってこと。)

ただし、上記の問題は、実装クラスのアクセス指定をpublicにしなければいいだけなので、全然に大した問題ではありませんけどね。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-07-12 00:13
unibon です。こんにちわ。

引用:

お犬様さんの書き込み (2003-07-10 11:57) より:
interface に対する不満としては 他にも interface に public static な
メソッドを書けても良いじゃないか、とかいう話を聞いた事があります。


これについて Sun の Bug Database を探していたら見つけました。
http://developer.java.sun.com/developer/bugParade/bugs/4093687.html

なお、このへんを探していると、私の最初の疑問と似た話として、
http://developer.java.sun.com/developer/bugParade/bugs/4144491.html
http://developer.java.sun.com/developer/bugParade/bugs/4193599.html
http://developer.java.sun.com/developer/bugParade/bugs/4193604.html
http://developer.java.sun.com/developer/bugParade/bugs/4230610.html
http://developer.java.sun.com/developer/bugParade/bugs/4456057.html
などが見つかりました。
ただしこれらのページでは、内部クラスについての言及がなさそうであり、そのせいか、
public 以外のメソッドの必要性はあまり高くない、
という論調になっているような気もします。
#上記のページは、まだあまり良く読んでいないのですが。

あと、私の考えを補足しますと、
極端な話、interface であってもメソッドに private すら使えても良いと思います。
この場合、そのメソッドの実装が絶対にできないので、
その interface を implements している class のコンパイル時にはコンパイルエラーになりますが、
だからと言って interface の時点にまでさかのぼって private を禁止することは、
キレイだと感じません。
asip
ベテラン
会議室デビュー日: 2001/12/27
投稿数: 77
投稿日時: 2003-07-12 11:58
>interface の時点にまでさかのぼって private を禁止することは、
>キレイだと感じません。

interfaceにpublic以外のメソッドを追加するために言語仕様を変更する事に
下位互換性を犠牲にするほどのメリットがあるとは思えません。

interfaceの構文に変更を加えるためには、バイトコードレベルでの変更が
必要であり、VM自体の変更が必要になるはずです。

VM自体が変更されると必然的に、interface構文変更前に書かれたプログラムは
そのままでは(書き換えない限り)interface構文変更後のVMでは動作しなくなります。

つまり、interface構文を変更すると下位互換性がなくなるのです。

このことはinterface構文変更後のVMで動かすためにはinterface変更前の構文で書かれた
プログラム全てを修正する必要があることを意味します。

interfaceにpublic以外のメソッドを追加するための言語仕様変更に下位互換性を
犠牲にしてまで行うほどのメリットがあるとは思えないのですが、下位互換性を
犠牲にしてもよいほどのメリットがあるのならぜひ教えてください。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-07-12 12:46
unibon です。こんにちわ。

引用:

asipさんの書き込み (2003-07-12 11:58) より:
interfaceにpublic以外のメソッドを追加するための言語仕様変更に下位互換性を
犠牲にしてまで行うほどのメリットがあるとは思えないのですが、下位互換性を
犠牲にしてもよいほどのメリットがあるのならぜひ教えてください。


大きなメリットはないです。しいてあげるとしたら、つぎの2点位でしょうか。

(1) 初心者が理解し易くなる。
もし private/protected があったほうが理論的にスッキリするのならば(という仮定がありますが)、
私のように、どうして interface に private/protected がないのか、を悩まなくて済みます。
教えるほうも、class と interface の類似性をより強調できて、楽になります。

(2) 将来、Java を大幅に拡張・変更する機会(C# なども含む)があったときに、
『ああ、そういえばそんな RFE(Request for Enhancement) があったなあ。これも足しとくか。』
となるかもしれません。

言語仕様や VM 仕様を変えるかどうかは、また別に考えれば良いと思います。
初期の C++ が C にコンバータ(?)のようなものを追加していたような感じや、
あるいは単に IDE(統合開発環境)上でだけ、あたかも private/protected が使えるように見せかけるだけ、
などのように、言語仕様や VM 仕様を変えずにできる可能性もありますし。
#でも、良くありがちな、コメントや命名規則でやりくりするのは、
#個人的な好き嫌いとしてはややこしくてイヤだ(笑)。

もっともたかが(と言ってしまうとみもふたもありませんが)、
private/protected のためにそこまでしなくても、単に開発者が頭の中で、
『これ、ホントはこっちのほうが良いんだけど、過去の経緯でこうなってるんだったなあ』
と置換するだけでも良いです。

#以下、追加。

あと、下位互換性(backward compatibility)についてですが、
たとえば JDK 1.4 のデフォルトの設定で生成した .class ファイルは、
ファイルのフォーマットが違うため、古い JDK の環境では動かないことがありますし、
あと、シリアライズなども下位互換性がなかったと思います
(フォーマットは -target オプションを付けてコンパイルすればよいし、
シリアライズについては VM とは無関係かもしれませんが)。
だから、下位互換性はなくても良いと思います。
#もちろんあったほうが良いけど、もうすでにないので、
#private/protected の場合もさほど拘らなくてよいのでは、という意味です。

[ メッセージ編集済み 編集者: unibon 編集日時 2003-07-12 12:58 ]
お犬様
ベテラン
会議室デビュー日: 2003/01/26
投稿数: 67
投稿日時: 2003-07-12 14:54
引用:
unibonさんの書き込み (2003-07-12 12:46) より:

初期の C++ が C にコンバータ(?)のようなものを追加していたような感じや、あるいは単に IDE(統合開発環境)上でだけ、あたかも private/protected が使えるように見せかけるだけ、などのように、言語仕様や VM 仕様を変えずにできる可能性もありますし

そのようなお考えであれば、ご自分でプリプロセッサを お作りになるのが手っ取り早いかと思います。リフレクション経由でのアクセスに関しては従来どおりになってしまいますが…

引用:
unibonさんの書き込み (2003-07-12 12:46) より:

あと、下位互換性(backward compatibility)についてですが、たとえば JDK 1.4 のデフォルトの設定で生成した .class ファイルは、ファイルのフォーマットが違うため、古い JDK の環境では動かないことがありますし、

interface に protected なメソッドの記述を許せば asip氏が仰るように VM を書き換える必要がありますし、そのような仕様で書かれたソースは -target を指定してコンパイルしても古い JRE で動く保証がなくなりますので、同列に扱ってよい話では無いと考えます。

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