- PR -

class or interface ?

投稿者投稿内容
Jun
大ベテラン
会議室デビュー日: 2003/08/25
投稿数: 141
投稿日時: 2003-08-27 18:23
私はinterfaceの継承は包含関係であると考えています.
この点でinterfaceの継承はクラスの継承と異なっています.
つまり包含関係であればダイアモンド継承しても同じinterfaceに属する
ものは常にユニークです.従って多重継承にまつわる問題はinterfaceでは
発生しないということかと思います.
従ってinterfaceを継承するということはinterfaceによってクラスを分類する
ということになります.この分類するという機能はclassの継承によっても得られる
ことですから, これにより多態性が実現できるということだと思います.
言い換えると多態性を実現するためには継承によるクラスの分類機能とオーバーライド
のみがあればよいということです.

分類ですからinterfaceのメソッドにアクセスできる必要はありません.
たんにそういうアクセス修飾子を持ち, シグネチャを持ったメソッドが存在すると
いうことだけです. 従ってinterfaceのメソッド(もっといえばネストしたクラスと
これだけは制限はつくけどデータ属性と)がpublicである必要は本質的に無い
ということをいっているのです.

つまりこのように考えればinterfaceは単なるabstract class と同じだがimplementsに
より継承するものではなく, 単なる宣言と思えばよろしいかと思います.
宣言ならprivateやprotected も宣言できて当然ですよね.
一見publicでなければアクセスできないから使えないと思ってしまいそうですが
元々使ってなどいないのです.そういうメソッドを実装してくださいという意味にす
ぎません.したがってprotectedやprivate も有用であることがお分かりと思います.

protected なメソッドをinterfaceのメソッドにできればそれをimplementするクラスは
少なくとも継承階層のどこかでprotectedなメソッドを実装する必要があります
これは手続き型プログラミングでいうとcallbackルーチンに相当する処理
(Cでいうと関数ポインタを使うような処理) に対して非常に有効です.
これらの処理をオブジェクト指向の多態性を利用した処理に置き換える場合
protectedなメソッド(本当はprivateであるべきだが, 残念ながらprivateなメソッドの
オーバーライドはjavaではできない.)がでてきます.
このprotectedなメソッドの実装を強要する(実装しなければコンパイル時エラーが
発生するようにする) のにinterfaceのなかでのprotectedメソッドの宣言がしたいわけ
でする

Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2003-08-27 19:42
Wataです。

引用:

Junさんの書き込み (2003-08-27 18:23) より:
一見publicでなければアクセスできないから使えないと思ってしまいそうですが元々使ってなどいないのです.そういうメソッドを実装してくださいという意味にすぎません.したがってprotectedやprivate も有用であることがお分かりと思います.


決して使われることのないメソッドを実装することを強要することにどんな意味があるのですか?理解できません。privateなら実装することすらできません。

引用:

protected なメソッドをinterfaceのメソッドにできればそれをimplementするクラスは 少なくとも継承階層のどこかでprotectedなメソッドを実装する必要がありますこれは手続き型プログラミングでいうとcallbackルーチンに相当する処理(Cでいうと関数ポインタを使うような処理) に対して非常に有効です.


不可能ですよ。もし、ActionListenerのactionPerformedメソッドがprotectedだったら、リスナをButtonに登録しても、Buttonクラスにはメソッドは不可視なのでコールバックすることができません。
まさか、インターフェイス内のインナークラスからコールバックするのですか?

だから、いったい誰が呼ぶのかと聞いていたのですが...。

#追記
引用:

Junさんの書き込み (2003-08-27 15:35) より:
そのことの証拠としてinterfaceの中で定義されているネストしたクラスをimplement
したclassから使用するときはinterface名での修飾が必要となります.


そんなことはありません。不要です。

[ メッセージ編集済み 編集者: Wata 編集日時 2003-08-27 19:58 ]
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-08-28 12:32
ども、ほむらです。
いいたいことのほとんどはWata氏が書いているので
その他をすこし。。。
--------------------
Jun氏へ
出だし部分はすこし極論的なところ以外は共感を得たりもしていますが
引用:

言い換えると多態性を実現するためには継承によるクラスの分類機能とオーバーライド
のみがあればよいということです.

分類ですからinterfaceのメソッドにアクセスできる必要はありません


オーバーライドするためには必ずアクセスできなければならないと思います。
あと、class内部では包含関係として同一のものと判断しているようですが
僕が使用した感じだとスコープの保持はされているようです。
この時点で、アクセス修飾子は意味をもって
継承したかのような状態も作られてしまうのでないでしょうか?
(よう、implementsしたclassからも見えなくなってしまうといいたいのです)

引用:

protected なメソッドをinterfaceのメソッドにできればそれをimplementするクラスは
少なくとも継承階層のどこかでprotectedなメソッドを実装する必要があります
これは手続き型プログラミングでいうとcallbackルーチンに相当する処理
(Cでいうと関数ポインタを使うような処理) に対して非常に有効です.
これらの処理をオブジェクト指向の多態性を利用した処理に置き換える場合
protectedなメソッド(本当はprivateであるべきだが, 残念ながらprivateなメソッドの
オーバーライドはjavaではできない.)がでてきます.
このprotectedなメソッドの実装を強要する(実装しなければコンパイル時エラーが
発生するようにする) のにinterfaceのなかでのprotectedメソッドの宣言がしたいわけ
でする


まず始めに
コールバック関数はいつでもどこからでもアクセスできることが大前提だと思います。
これはワーカースレッドはともかくとして
メッセージスレッドについても同じことが言えるはずです。
(個人的にはワーカースレッドも隠蔽すべきではないと思っていますが)

あともう一点。
ただ、宣言の強要したいだけであるのならばinterfaceに含めなければ
それだけでコンパイル時にエラー出ると思います(未定義という形ですけど(笑)

#protectedで宣言したいという人達はなににprotectedを使用したいのかがわからない
#いや、callback関数なのかな? でもそれだとどうやって使うつもりなのだろう?
#コンパイルとおらなくても良いからサンプルがほしいな〜とおもってみたり。。。
Jun
大ベテラン
会議室デビュー日: 2003/08/25
投稿数: 141
投稿日時: 2003-08-28 14:07
ちょっと例をあげましょう

いま仮にprotectedなメソッドをinterfaceにかけるとして
interface RR
{
protected abstract void mR();
}
public abstract class A extends AA implements RR
{
public void m(int i){mR();...}
}
public abstract class B extends BB implements RR
{
public void m(String s){mR();...}
}
public class AAA extends A
{
protected void mR(){...}
}
public class BBB extends B
{
protected void mR(){...}
}
public class ...
{
...{
RR rr[] =
{
new AAA(),
new BBB(),
};
...
}
のようなものを現状では
interface RR{}
public abstract class R implements RR
{
protected abstract void mR();
}
public abstract class A extends AA implements RR
{
protected abstract void mR();
public void m(int i){mR();...}
}
public abstract class B extends BB implements RR
{
protected abstract void mR();
public void m(String s){mR();...}
}
public class AAA extends A
{
protected void mR(){...}
}
public class BBB extends B
{
protected void mR(){...}
}
public class ...
{
...{
RR rr[] =
{
new AAA(),
new BBB(),
};
...
}
のように書かないといけないですよね.この例だとabstractメソッドは一つですから
どっちでも同じようですがこれがたくさんあったりまたRRのようなものを複数継承する
必要があるとしたら委譲を使わざるを得ないと思います.
しかしながらもしprotectedなメソッドをinterfaceに書くことが許されれば型RRという
ものを定義するだけですみますよね.
この例のprotectedメソッドはそれの存在を定義するものですからpublicでないといけない
ということは無いはずだといっているのです.
ぽん
大ベテラン
会議室デビュー日: 2003/05/13
投稿数: 157
投稿日時: 2003-08-28 14:53
Junさんに質問です。

引用:

Junさんの書き込み (2003-08-28 14:07) より:

RRのようなものを複数継承する必要があるとしたら委譲を使わざるを得ないと思います.



1.何故Interfaceを複数継承する場合、委譲を使わざるを得ないのですか?
 (複数のInterfaceを継承していて、委譲を使用してないクラスが存在します)
2.委譲を使うことで重大なデメリットが発生しますか?
 (書くのが面倒だとかですか?)

お答え頂ければ幸いです。

[ メッセージ編集済み 編集者: ぽん 編集日時 2003-08-28 14:56 ]
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-08-28 15:20
ども、ほむらです。
間の抜けた質問をして申し訳ないのですが
JAVAでは上位のクラス(派生元)から下位のクラス(派生先)を
呼び出すことが出来るのですか?

提示していただいたソースはたとえprotectedが許されたとしても
かなり危険で、文法的にもあやしいプログラムだと思うのですが。。。
今のところの僕の知識ではinterface の mR()を呼び出すための手順が思い浮かびません

それと明記はされていませんが class AAとclass BBを宣言する時点で
RR_Baseみたいなクラスを継承する形ではいけないのでしょうか?
class AA extends RR_Base
class BB extends RR_Base
みたいな
yamasa
ベテラン
会議室デビュー日: 2003/02/15
投稿数: 80
投稿日時: 2003-08-28 15:23
引用:

Junさんの書き込み (2003-08-28 14:07) より:

これがたくさんあったりまたRRのようなものを複数継承する
必要があるとしたら委譲を使わざるを得ないと思います.


委譲は「使わざるを得ない」ものでなく、むしろ
積極的に使うべきものだと私は思います。

そもそも、Junさんが挙げられた例は継承を使っている意味がないでしょう。
コード:
RR rr[] = 
{ 
new AAA(), 
new BBB(), 
};


この部分で、AAA, BBBのインスタンスをRR型の配列に入れて、何をするつもりなんですか?
RR型で唯一宣言されているmR()メソッドはprotectedなのでアクセスできませんし。


少し話を戻しますが、
引用:

Junさんの書き込み (2003-08-27 18:23) より:

これは手続き型プログラミングでいうとcallbackルーチンに相当する処理
(Cでいうと関数ポインタを使うような処理) に対して非常に有効です.
これらの処理をオブジェクト指向の多態性を利用した処理に置き換える場合
protectedなメソッド(本当はprivateであるべきだが, 残念ながらprivateなメソッドの
オーバーライドはjavaではできない.)がでてきます.


これはいわゆるTemplate Methodパターンですよね。
しかし、同様のことはStrategyパターンを用いてもできます。
こちらは委譲ベースのパターンなので、メソッドのアクセス制限を
意識する必要はありません。

Junさんの悩みも、Template MethodからStrategyへの置き換えをすれば
すぐに解決するものではないですか?
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2003-08-28 16:03
引用:

Junさんの書き込み (2003-08-28 14:07) より:
>しかしながらもしprotectedなメソッドをinterfaceに書くことが許されれば型RRという
ものを定義するだけですみますよね.



この程度の目的のために、protected(またはprivate)なメソッドをinterfaceに定義する
ことを許すのですか? interface本来の目的から外れる定義を許すのなら、「そうしなければ
できない」こと、あるいは「大きなメリットが得られる」ことでなければならないでしょう。

そうでなければ、Javaの言語仕様はどんどん膨れ上がって複雑怪奇なものになると思います。

引用:

ほむらさんの書き込み (2003-08-28 15:20) より:
ども、ほむらです。
間の抜けた質問をして申し訳ないのですが
JAVAでは上位のクラス(派生元)から下位のクラス(派生先)を
呼び出すことが出来るのですか?



これができなければTemplate Methodパターンを実装することができないということに
なってしまいますが。

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