- PR -

class or interface ?

投稿者投稿内容
Jun
大ベテラン
会議室デビュー日: 2003/08/25
投稿数: 141
投稿日時: 2003-08-29 18:16
引用:

ほむらさんの書き込み (2003-08-29 17:27) より:
ども、ほむらです。
-------------
Jun氏へ
引用:
コード:
interface RR 
{ 
  protected abstract void mR(); 
} 
public abstract class A extends AA implements RR 
{ 
  public void m(int i){mR();...} 
} 



呼び出せないといったのはこの部分です。
あとで個人的にabstractの記述は省略しただけかなと理由つけていますが。。。
この状態では class A からでも mR()は呼び出せないように思えます。



これは現仕様ではpublicなものしか定義できないということからそのように考えるのは
無理も無いと思いますが, 話が現仕様を変えたほうがよいのではということですから
これも呼び出せるように仕様を考えるということです.
つまりinterfaceに記述されたメソッドはそれをimplementsしたクラス中の
継承階層でinterface以外の最下層で同じように定義されているとみなすことにします.
そうすればprotetedどころかprivateだって意味を持ちます.
逆にいうとこのように考えないとpublicしか定義しようが無いと思いますが
いかがでしょう

ついでにネストしたクラスやstaticなデータ属性も同じように考えます.
従ってネストしたクラスへのinterfaceによる修飾は不要です
ついでにもうひとついうとこのようにした場合interface同士の継承関係は
現状のようにextendsをもちいるのでなく, すべてimplementsを用いるべき
とおもいます.つまりextendsは実装を含む継承を表し, implementsは
仕様のみの継承を表すというように

ついでにもうひとつこの話とは関係なく付け加えてもらいたいと思う機能は
クラスのインターフェースをimplementsにより継承できるようにしてもらいたい
などというのもあります

たとえば

public class A{}

public class B implements A{}

とするとB はAと同じメソッドを仕様として持つがその実装は継承しない
こういう機能があるとすでに出来上がった外部のクラスを利用するとき便利
と思ったのです.
Astmild
常連さん
会議室デビュー日: 2003/06/09
投稿数: 30
お住まい・勤務地: 大田区
投稿日時: 2003-08-29 18:39
こんにちは。
ちょっと水を差します。

この議論の平行線は、interface について

Junさん:「(狭義の)仕様」を定義するもの
反論する皆さん:「(広義の)仕様」と「実装」を分離させるもの

という認識の違いから起こっているように思います。


一度それぞれのメリット、デメリット、根拠を明らかにして
両方を俯瞰してみてはいかがでしょうか?
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2003-08-29 19:21
引用:

interface同士の継承関係は現状のようにextendsをもちいるのでなく, すべてimplementsを用いるべきとおもいます.つまりextendsは実装を含む継承を表し, implementsは
仕様のみの継承を表すというように



interface A {}
interface B implements A {}
のようにすべきであるといっているのだと思うのですが、インターフェースBはインターフェースAを実装しているの?
むしろAの機能(責任)を拡張しているものであり、extendsを使用することに何ら問題はないと思いますが?

引用:

クラスのインターフェースをimplementsにより継承できるようにしてもらいたい
などというのもあります

たとえば

public class A{}

public class B implements A{}



これは、あらかじめAから抽象仕様を抽出しておくことで、解決できる問題なので、必要ないでしょう。

public class A implements IF_A {}
public class B implements IF_A {}

ってな感じで。
Astmild
常連さん
会議室デビュー日: 2003/06/09
投稿数: 30
お住まい・勤務地: 大田区
投稿日時: 2003-09-01 02:05
引用:

Astmildさんの書き込み (2003-08-29 18:39) より:
この議論の平行線は、interface について

Junさん:「(狭義の)仕様」を定義するもの
反論する皆さん:「(広義の)仕様」と「実装」を分離させるもの

という認識の違いから起こっているように思います。


これについて、このように考えてみました。


(1)interface を「(狭義の)仕様」を定義するもの と考える場合

メリット:
・設計者の思い通りの実装が行われる

デメリット:
・設計者の能力に依存する
・実装者に自由がない

根拠:
・大抵のJava入門書には「interface はクラス宣言と似たものと考えることができ、
多重継承の解決に用いることができる」と書いてある


(2)interface を「(広義の)仕様」と「実装」を分離させるもの と考える場合

メリット:
・設計者の労力を低減させることができる
・実装者が創意工夫を発揮することができる
・interface は実装クラスへの role(役割) の付与である、という捉え方ができ、
そのシステムがどんな構造であるかを理解しやすくなる

デメリット:
・OOA、OOD、デザインパターンを知らないと使いこなすのが難しい

根拠:
・仕様と実装の分離はハードウェアの開発に良いやり方であり、それはソフトウェアの
開発やシステムの開発にも当てはまるため、Javaにも導入されたと考えられる。


(1)のように考えれば、protected が使えても良いのではないか、という主張も
うなずけます。ですが、そうあった時のメリットが私には浮かびませんでした。
また、Java の入門書で根拠のような意味の記述をよく見かけるのを不思議に思いました。
(2)のように考えると、メリットは大きいと思います。使用するのは設計段階なので、
デザインパターンモデリングを知っていれば、より活用できると思います。


お互いが違う認識をしているために、議論が平行線だったように思えたので
水を差した(というか、鎮火した?)んですが、いかがでしょう?
Jun
大ベテラン
会議室デビュー日: 2003/08/25
投稿数: 141
投稿日時: 2003-09-01 09:53
引用:

よつもとさんの書き込み (2003-08-29 17:50) より:
引用:

Junさんの書き込み (2003-08-29 15:34) より:
いや, これは RR は概念的な一つの型であるといっているのです.mR はその型に属する
具象クラスで定義されるメソッドだけどそれは直接外部から呼んでほしくない
ただそのメソッドを使うプロトコルがあって, それはメソッドで定義されているから
そちらを呼んでくださいということです.


結局、interfaceであるRRの中で「mRのメソッドを呼び出しなさい」という暗黙の強制をしていることになりますね。


それは違います. 呼び出しなさいということでなくmRを実装しなさいということでしょう
mRが実装されないと意味が無いのでmRを実装してくださいということです
mRの呼び出しはしてはいけません.本当はprivateにしたいといったのはそういう意味です
mRの呼び出しはすでに実装されておりそれを通常変える必要はありません
(もちろんオーバーライドできるかどうかは呼び出しメソッドがfinalであるかどうか
であってそれはこの話には関係ないですね)
Jun
大ベテラン
会議室デビュー日: 2003/08/25
投稿数: 141
投稿日時: 2003-09-01 10:05
引用:

かずくんさんの書き込み (2003-08-29 17:56) より:
引用:

例えば乗り物をinterfaceとします
乗り物の具象クラスには車やバイクなどがあるとし, それらには走らせるという
メソッドや操作するための他のメソッドがあるとします.
これらのメソッドを使って乗り物を操作しても良いのですが面倒だからこんなことは
したくないと思って例えば次のようにします
乗り物にコンピュータを組み込み, そのコンピュータは目的を与えられれば勝手に
乗り物を操作し, 目的を達成してくれるのです.
こうなったら乗り物の操作を覚えている(=publicである)必要はありません.
その場合乗り物とは何か操作するメソッドがある(それはコンピュータにより必要
とされるメソッドであり何が必要か決まっているが(=interfaceにある) そのメソッド
は使えなくて良い(=publicでなくてよい))



以下の様なコードが自然だと思うのですが。もちろんinterfaceにはprotectedなメソッドを必要としません。
コード:
interface Vehicle {
	public void drive();
	public void setDriver(Driver inDriver);
}

interface Driver {
	public void drive();
}

class Car implements Vehicle {
	Driver mDriver;
	
	public Car() {
		mDriver = new ComputerDriver();
	}
	
	public void setDriver(Driver inDriver) {
		mDriver = inDriver;
	}
	
	public void drive() {
		mDriver.drive();
	}
}

class HumanDriver implements Driver {
	public void drive() {
		...
	}
}

class ComputerDriver implements Driver {
	public void drive() {
		...
	}
}

public class Main {
	public static void main(String inArgs[]) {
		Vehicle aVehicle = new Car();
		
		aVehicle.drive(); // こんぴゅーたー様が車を運転
		
		aVehicle.setDriver(new HumanDriver());
		aVehicle.drive(); // 一市民が車を運転
	}
}




私の言っているのはそういうことでなくて, ドライブを意識するのはライブラリ
構築側で行う(つまりあなたのコードのように)
しかし提供するときにはドライブというメソッドを意識させない

例えば目的地だけ教えると乗り物が勝手に目的地へつれていく.従ってドライブ
というメソッドはあるけれども非公開ということなのです.そのメソッドは
ライブラリ設計者のみが使うということです.

オブジェクトを非常に多く使えるようにするためには, そのオブジェクトが
プロトコルを持たないようにすることが必要になると考えているんですけど
プロトコルはどうしても発生するものですから, それをオブジェクトの内部に
押し込めてしまって外部からは見えなくすればいいわけです.
もちろんそれを継承したりしてオブジェクト指向の部品として使うには
不便になりますが, 単なる拡張された型として意識するなら使いやすい
ものになると思います.
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-09-01 10:50
おはようございます。ほむらです。
鎮火したというより週末で一時停止中でした(笑
-------------
さて、今の僕には protected が使えてはダメということの説得が出来ないようですので
その部分は割愛させていただきます。
しかし!一つ無視されてしまっているようなのでだらだらとかきます。

Jun氏は現在の仕様でオーバーライドが出来ないからprivateを使用しないといっていますが
privateにしたらオーバーライドできないのは
Javaの使用ではなくてオブジェクト指向におけるカプセル化という考え方に
起因していると思います。

つまり、本来であればprivateとpublicの二つでいいはずなのに
継承という考え方とあわせたときの都合上protectedが存在したのではないかと。。。

privateで指定されたものはそのオブジェクト内でしか使用できません。
継承した先では見えなくなります、これは、隠蔽という行為が
他のオブジェクトとの干渉を考えなくても良い強力なメリットであると同時に
機能拡張を目的とする継承したオブジェクトにとってはデメリットにもなります。
かといってpublicにしてしまってはprivateのメリットは生まれません。
だから、protectedが出来たんじゃないかと僕は考えています。

実装されなければオブジェクトとして意味をもたないメソッドを隠蔽することの意味が
僕には想像できませんが、このメソッドをprivateで指定した場合には
継承と似た作用のあるimplementsを使用した場合でも継承先には見えません。
見えない時点でのオーバーライドも不可能でしょう。
オーバーライドは基底クラスの元となる関数も呼び出せることが絶対条件です。

見えないものをオーバーライドするこれを理由に
見えるようにしてしまった時点で
オブジェクト指向という考えは破綻するものと思います。
(当然extendsでもオーバーライド可能になるためというのもあります)

#オフとぴ
以前のコードで僕が言いたかったのは
コード:
public abstract class A extends AA implements RR 
{ 
  public void m(int i){mR();...} 
} 
ではなくて
public abstract class A extends AA implements RR 
{ 
  protected abstract void mR(); 
  public void m(int i){mR();...} 
} 
とあるべきじゃないかなと。。。


酒樽
会議室デビュー日: 2002/06/06
投稿数: 10
投稿日時: 2003-09-01 12:21
引用:

Junさんの書き込み (2003-09-01 09:53) より:
引用:

よつもとさんの書き込み (2003-08-29 17:50) より:
結局、interfaceであるRRの中で「mRのメソッドを呼び出しなさい」という暗黙の強制をしていることになりますね。


それは違います. 呼び出しなさいということでなくmRを実装しなさいということでしょう
mRが実装されないと意味が無いのでmRを実装してくださいということです
mRの呼び出しはしてはいけません.本当はprivateにしたいといったのはそういう意味です
mRの呼び出しはすでに実装されておりそれを通常変える必要はありません


これは誤解を生む書き方だったようです。
ですが、この回答ではっきりしました。
mRがabstractでなくコードを伴った実装であり、それをinterface自身に装備することが要望であれば、それは私が理解しているinterfaceの目的「入出力の規格を規定するもの」とは異なるものです。
引用:

オブジェクトを非常に多く使えるようにするためには, そのオブジェクトが
プロトコルを持たないようにすることが必要になると考えているんですけど
プロトコルはどうしても発生するものですから, それをオブジェクトの内部に
押し込めてしまって外部からは見えなくすればいいわけです.


ここで言うプロトコルとは、アルゴリズムのことでしょうか。
独自の用語は極力使わないか、どうしても必要なら日本語で解説してもらえると助かります。

こういう方法は、コードが分散しないという意味では一理あるのかもしれませんが、それは本質ではありません。むしろinterfaceが持つ良い意味での制約に影響を及ぼす、ダーティーな仕組みと考えています。
それを許すかどうかは改良というレベルではなく、Java言語の設計思想の見直しから考える必要がある論議ではないでしょうか。

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