1 :
デフォルトの名無しさん :
04/05/14 18:08 全部コンポジションでいいやん。 継承はインターフェースだけで。
2 :
デフォルトの名無しさん :04/05/14 18:08
2
VBこそが正義
漢なら多重継承!
消えろ
VBを使うべきだ
親クラスは子クラスに対して開かれているから 実装継承はカプセル化の概念を壊す。 継承関連は静的に決定するから柔軟性も制限される。 コンポジションを使えばオブジェクトに対するアクセスは インターフェースに限定されるのでカプセル化の原則は守られる。 実行時にオブジェクトの交換も出来る。 システムの振る舞いも関連に依存する。 ついでにヨーヨー問題も起こらない。 漏れは何も間違っていないはずだ。
9 :
デフォルトの名無しさん :04/05/14 18:46
オブジェクト指向はちっとも直感的でない。 しかも複雑な状態管理を人間が完璧にやってのけることを前提としている。 その前提自体が誤りだ。 その証拠に現実のソフトウェアはバグだらけだ。
抽象クラスはどうなるんだ? Template Methodパターンはどう実現するのか? 親クラスの内部実装引っ掻き回すためだけの継承なら俺も大反対だが、 何事も使い分けだろ。
こんなんだめ? Template Methodパターン。 template<class Impl> class Hoge{ Impl impl_; public: void hoge(){ impl_.hoge(); } };
>>9 俺も手続き指向のほうが人間の思考に楽に一致すると思うし、
特に手続き思考経験者がオブジェクト指向に馴染むには一回発想を
ひっくり返さなくちゃいけないから大変だとおもうが、
お前さんは単にオブジェクト指向わかってないだけ。
複雑な状態管理から目をつぶるための仕組みがオブジェクト指向だ。
13
ていうか
>>12 も全然わかってないと思う。
>手続き思考経験者がオブジェクト指向に馴染むには一回発想を
>ひっくり返さなくちゃいけない
こんなのヘタレな人だけだし。OOサポートしてる言語使うか否かにかかわらず
ある程度複雑なプログラムならOO的に設計するし。なんかgoto使うのがスパゲティ
みたいな誤読がずっとまかり通ってるけど、本来のスパゲティコードってのは
goto使ってるかどうかなんてことじゃなくてOO的に設計されていないコードのことを言う。
オブジェクト指向ってのは別に手続き型のコーディングの否定じゃなくて延長だし。
状態管理?それオブジェクト指向と直接関係なくないか?
>>1 それってStrategyパターンじゃないの?
StrategyパターンとTemplate Methodパターンは似てるけど、
Template Methodのメリットって、クラス自身が手順を知ってることでしょ?
16 :
デフォルトの名無しさん :04/05/14 20:00
17 :
デフォルトの名無しさん :04/05/14 20:02
コンポジションやインターフェースは無駄な糊コードが増えるから 生産性が激減するというのは業界の常識なわけだが。
時代は副作用レスの関数型
全部privateにしちゃったらクラスにする意味ってあるのかな・・・ 構造体でいいような・・・ 先週始めたばかりだからよくわかってない。すまぬ
>>15 ごめん省略しすぎた。これで。
template<class Impl>
class Hoge{
Impl impl_;
public:
void hoge(){
impl_.method1();
impl_.method2();
}
};
>>16 レイヤリングで解決できるところはprivate継承より
レイヤリング選択すべきだろ。
Effective C++ぐらいよんどけ。
ってか全部 privateにしたらダルマじゃん どうやってオブジェクト操作すんだよ あ、オブジェクト作成時に全ての処理を終わらせてしまえばいいや!!!!111
そこでプロトタイプベースの出番ですよ
C++は廃止すべき
>>17 再利用性可能なOODにおいては、
・インターフェースに対してプログラミングする
・クラス継承よりコンポジションを多用する
ってのはGoF本読んだ奴にとっては常識だと思ってたのだけど。
それを踏まえて、実装継承なんて言語機能に必要ないんじゃないか
と主張したいわけだ漏れは。
>>23 プロトタイプベースと言うとselfとか?
悪い勉強不足だ。今度勉強しておく。
>>24 漏れがC++よく使うから例に出しただけだ。
別にC++の話をしてるわけじゃない。
>>1 で、外部のライブラリのカスタマイズ時にやらざるを得ない場合を除いて
普段の開発では一切実装継承してないのか?
>>28 個人でやるときは。
漏れも実装継承はいらないと思い始めたのはごく最近なのだが。
インターフェースの設計を注意深くする必要があるが、
オブジェクト間の依存をインターフェースのみに減少できるので、
実装依存度は低くなり再利用性は高まる。
あと言語に操作の委譲構文があればもうちょっと楽になると思う。
30 :
デフォルトの名無しさん :04/05/14 23:43
>>1 抽象クラスが本質的に持つべき操作ってのは
抽象クラスに実装してもいいと思うけどね。
ただ、具象クラスのうちほとんどが同じ処理するから
抽象クラスのほうに実装しちゃえ、ってのは安易だよな。
>>14 いや、スパゲッティてのはgotoで「出入り口ひとつ」を無視して
上に下に飛びまくるプログラムのことじゃないか?原義は。
FORTRAN77とかN-BASICで適当に書くと自動的にそうなるような。
OO的に書いてないのはスパゲッティ、てのは違うと思うが。
たとえば、順接、反復、分岐の原則を守った上で1プログラム1関数で
1関数1万行でインデント100段付くようなプログラムはOO的では
ないがスパゲッティとも違うような・・・
(スレ違いすま)
継承を昇華したものがインターフェースなのでは。
>>32 ちがう。
インターフェースはオブジェクトの操作によって
定義されるシグニチャの纏まりのこと。
ついでにインターフェースの表現として用いるのがタイプ。
あってもいいやん?
>>33 追記。
例えば、Humanというインターフェースで定義された操作に対する
要求をすべて受け付けるオブジェクトはタイプHumanを持つ。
サブタイプがスーパータイプのインターフェースを有することが
インターフェース継承。
一方、サブクラスがスーパークラスの全ての属性と操作を含むのが
クラス継承。
>>32 の主張は根本的な理解が間違ってる。
>>1 まずは最低10万行のプロジェクトで継承をまったく使わない
やり方を試してみてメリットとデメリットを検証しろ。
話はそれからだ。
>>1 俺Java厨だから(C++は大雑把に知ってる)
テンプレートを勘違いしてたらゴメンだけど、
20のソースはTemplate MethodじゃなくてStrategyだよ。
method1()とmethod2()を持ってるのはHogeじゃなくてImplなわけだから、
手順を表すvoid hoge()がImplのメンバーじゃない限り、
それはStrategy。
あと、不注意に作られたクラスを継承するときはともかく、
きちんと考えて書かれたクラスって、最初から継承されること考えられて
書かれてるからいじられたくないフィールドはprivateになってるし、
外部からいじられたくないけど子クラスにいじって欲しい部分はprotectedにするから、
コンポジションでも継承でも設計の簡潔さは変わらない。
少なくとも俺のコードはそうしてる。
各サブクラスを見たときに、何がサブクラス独自の物か把握しづらくなるのは嫌だな
>>37 Template Methodって、アルゴリズムの各ステップの呼び出し順を規定して、
その中のいくつかに子クラスで実装を与えるパターンだと思ってたんだけど。
>>20 に具体例を与えると、
template<class Impl>
class Human{
Impl impl_;
public:
void attack(){
impl_.punch();
impl_.kick();
}
};
class Yamada{
public:
void punch(){ /*実装*/ }
void kick(){ /*実装*/ }
};
class Tanaka{
public:
void punch(){ /*実装*/ }
void kick();{ /*実装*/ }
};
int main(){
Human<Yamada> yamada;
Human<Tanaka> tanaka;
yamada.attack();
tanaka.attack();
}
これはTemplate Methodじゃない?
>子クラスで実装を与える というのを後から実装を与えると解釈した。
>>36 メリットは個々のクラスをカプセル化して1つの仕事に集中させれることか。
クラスの提供してる操作調べるのに継承階層行き来しなくてもすむのもメリット。
実装依存度が低くなることや他のメリットは今までさんざん書いてるから略。
デメリット?コード量が多くなることか?
そんなもん分析/設計時間に比べれば微小やし。
インターフェース継承はするんだからポリモルフィズムも使えるし。
>>1 なるほど、C++ではそうなるのか。
同じコードをJavaで書くとこうなる。
abstract class Human {
public void atack() {
punch();
kick();
}
public abstract void punch();
public abstract void kick();
}
class Yamada extends Human {
public void punch() { /*実装*/ }
public void kick() { /*実装*/}
}
class Tanaka extends Human {
public void punch() { /*実装*/ }
public void kick() { /*実装*/}
}
public class XXX {
public static void main(String[] args) {
Human yamada = new Yamada();
Human tanaka = new Tanaka();
yamada.atack();
tanaka.atack();
}
}
いけね、スペース普通に入れちまった。 abstract class Human { public void atack() { punch(); kick(); } public abstract void punch(); public abstract void kick(); } class Yamada extends Human { public void punch() { /*実装*/ } public void kick() { /*実装*/} } class Tanaka extends Human { public void punch() { /*実装*/ } public void kick() { /*実装*/} } public class XXX { public static void main(String[] args) { Human yamada = new Yamada(); Human tanaka = new Tanaka(); yamada.atack(); tanaka.atack(); } }
抽象化をテンプレートじゃなくてインターフェイスで行う言語だから こうなる。 これで継承を禁止されるとお飯の食いあげだよ。 でも、勉強させてもらったんでありがとさん。
46 :
デフォルトの名無しさん :04/05/15 02:57
言語なんて、それが良いか悪いかよりも それを使う人間によって良いか悪いかが決まるわけだと思うけど。 まあ、結局は特定のあるプログラムの話になっちゃうんだわな。 継承イイ(・∀・д・)クナイ! ってのも分かるが、分かりやすい部分もあるし。 上手く使えばいいんでない?
>>25 おまい、10年遅れの周回遅れ。
逝ってヨシ。
漏れも実装継承はいらないと思い始めたのはごく最近なのだが。 漏れも実装継承はいらないと思い始めたのはごく最近なのだが。 漏れも実装継承はいらないと思い始めたのはごく最近なのだが。 漏れも実装継承はいらないと思い始めたのはごく最近なのだが。 漏れも実装継承はいらないと思い始めたのはごく最近なのだが。 ( ´,_ゝ`)プッ
>>41 1の考え方、主張はとっても古いし独自解釈はいっちゃっててキモイんで、
さっさと人生リセットしちゃった方がいいと思いまーす
51 :
デフォルトの名無しさん :04/05/15 03:36
52 :
デフォルトの名無しさん :04/05/15 03:39
精神的ブラウザクラッシャー北キタ━(゚∀゚)━( ゚∀)━( ゚)━( )━(゚ )━(∀゚ )━(゚∀゚)━!!!!
54 :
デフォルトの名無しさん :04/05/15 03:52
人のホムペの意見コピペして、スレ立てする基地キタ━━━━━━(゚∀゚)━━━━━━ !!!!!
あと15レスぐらいしたら、今度は>1擁護の流れになる予定です
>>1 の自作自演(・A・)イクナイ!!
>>1 はオナーニのし過ぎ。匿名掲示板で一人でイク癖を直す必要がある
厨房って、なんで頭悪い癖に、他人の意見をさも自分の意見のように主張するんだろう? 出来の悪いクローン人間は、大気圏外へ廃棄処分の方向で。
gotoがいまだ廃止されていないにもかかわらず クラス継承の廃止を議論するのは時期尚早といわざるを得ない。
59 :
デフォルトの名無しさん :04/05/15 04:07
恥の上塗り。 さっさと大気圏外へどぞー
60 :
デフォルトの名無しさん :04/05/15 05:24
すまんが多重継承を多用しているんだがどう? シリアライズ属性を持つウィンドウクラスとか当然のごとくに多重継承させているが コンポジションはグルーコードがめんどくさ ダイヤモンド継承はまったく使わないがどうでしょう?
61 :
名無し@沢村 :04/05/15 05:26
クラス継承とはあくまでソースレベルでの書きやすさや自己満足のために使うものだ。 いくらオブジェクト指向を使っても、バイナリに翻訳された時点で、非オブジェクト指向化するんだから、プログラム的にはまったく意味がない。 それどころか非オブジェクト指向のソースをバイナリに翻訳した場合に比べて、冗長なコードが混じるだけのことだ。
1はキモイな。しかも知識がかなり浅い。
継承はなんつーか生理的に気持ち悪い。 実装してない機能を親からこっそり 引き継いでるなんてキモ過ぎる。 長嶋一茂と会話しながらも、後ろにミスターが立ってて 気が散って仕方ない、そんなシチュエーションに似ている。
リファクタリングのプルアップもやっぱり委譲かな?
>>48 じゃあ現在の考え方はどうなってんの?
漏れの勉強不足って可能性はあるから文献提示してくらはい。
>>52 そういえばそこも読んだことある気がする。
そこも漏れに影響を与えていると言われれば、それは確かにそうかも。
>>57 漏れが頭悪いのは確かだ。
でも自分の意見に説得力持たせる為に自分より名のある
他者の意見引用するのは普通だろ。
例外クラスのように継承関係で意味付けをしているものはどうするの?
言語仕様を変更する
>>71 // 例外オブジェクトのインターフェース
class Exception{
public:
virtual void method() = 0;
};
class SuperException: public Exception{
public:
virtual void method(){ /* なにか */ }
};
class SubException: public Exception{
SuperException super_;
public:
virtual void method(){ super_.method(); }
};
〜〜
try{
}catch(SuperException& e){
}
これじゃだめ?
1の理念に納得できる部分はあるんだけど、自然じゃない。 Cでオブジェクト指向やってるみたいな無理やりさがある。 継承は弊害があるがオペレーターオーバーロードほどじゃないし、 弊害を過大評価してメリットを捨ててるんじゃないか? 継承無しで実装できる自分の技術に酔ってるような気もするし。
>>74 継承はスーパークラスの実装とサブクラスの実装の結びつきを
密接にするから、スーパークラスの実装を変更した際に
サブクラスにまで変更を強いることがある。
責任を各クラスに完全に分散し、メッセージの要求にのみ
依存したコードを書いておけば、結果的にシステムの保守はしやすくなる。
弊害への対処だけじゃなく、十分にメリットもあると思う。
自然かどうかは漏れも考えた。
is-a関係、サブクラスがスーパークラスである関係ってのは、
サブクラスがスーパークラスの特性をすべて持っているってことだから、
サブクラスにスーパークラスを持たせるってのもそれほど不自然では
ないんじゃないだろうか。
>継承無しで実装できる自分の技術に酔ってるような気もするし。
ただ委譲してるだけだし、こんなの技術でも何でも無いよ。
>>75 >スーパークラスの実装を変更した際に
>サブクラスにまで変更を強いることがある。
言いたいことはわかるけど、逆にサブクラスにまで
変更を強制しなくてはいけないようなものこそ
スーパークラスで実装すると保守しやすくなって
メリットがあるんじゃないか?
けど実際書いてみるとそんなもんあんまりないんだよな。
議論が脳内で終わっている人のスレ。 参加者1名 傍観者1名 以上。
委譲しまくりだとデバッグで死にそうだな
>>77 ほんとに脳内で終わっているならこのスレは存在しないと思われ。
80 :
デフォルトの名無しさん :04/05/16 01:10
だからきみはばかだっていわれるんだよ、のびたくん
スネオ登場w
ドラえもんだろ。
>>75 >継承はスーパークラスの実装とサブクラスの実装の結びつきを
>密接にするから、スーパークラスの実装を変更した際に
>サブクラスにまで変更を強いることがある。
(プッ
馬鹿なだけじゃん。
>>83 実装継承の典型的なデメリットかと。
最初から完璧な設計なんてできないし。
85 :
名無し@沢村 :04/05/16 06:20
だからオブジェクト指向は意味ねーつの! いくらオブジェクト指向で書いても、非オブジェクト指向のバイナリに翻訳されるんだから、意味ねーの!! オブジェクト指向が意味を持つとしたら、CPUがオブジェクト指向で動くようになるときだけだ。
↑ dでもない馬鹿登場!
87 :
デフォルトの名無しさん :04/05/16 06:34
初心者だから、あまり良く分かってないんだけど、 ファクトリメソッドは、アブストラクトファクトリメソッドで書けということなん?
委譲より継承が優れている面。 1. 委譲するための転送関数を書くのが面倒。 2. 継承を使えばprivate,protectedで済んだメソッドが、委譲を使うと publicにする必要が出て来る。 3. インターフェースを委譲で実現すると管理すべきオブジェクトの 数が増えすぎる。継承なら単一のオブジェクトに複数のインターフェース をまとめることが出来る。 4. 委譲なら多対一・多対多の結び付きを簡単に実現できるが、 一対一の結び付きしか許したくないこともある。継承なら親と子が 一体のオブジェクトになっているので、自動的に一対一の結合になる。 1〜3は言語側に頑張ってもらうことも出来るが、機械語レベルで委譲に なっているだけで、良くも悪くも継承と変わらないことになりそう。 4は言語側ではどうしようもない。 結局、継承か委譲かは、オブジェクトを1つにするか複数にするかの トレードオフで決めるべきこと。ただ、構造としてどっちでも大差 無くて、protectedや自動型変換を使うために継承を使うとか、 バイナリ互換のために委譲を使うとか、そういうしょうもない理由で 決まっちゃうことが多いわけだが。
90 :
デフォルトの名無しさん :04/05/16 09:20
>1〜3は言語側に頑張ってもらうことも出来るが、機械語レベルで委譲に >なっているだけで、良くも悪くも継承と変わらないことになりそう。 間違った認識を、自信たっぷりに言い切る、その無意味な自信の根拠はナニ? 普通の人間は、そのあたりの「継承と委譲のトレードオフ」と呼び、 以降「オブジェクト間の相互作用」(collaboration図なんかで表される)をどう扱うか、 といったテーマに専念するもんだが。 一部の学者さんが、デザパタを素材に「研究」してるのもそのあたり。 わかりもせずに白黒付けたがる、その単純な性格は、リア工房と見た!!! 補足: 俺的に、学者さんがGoF25パターンのみ対象に研究するのは、あんま感心しない。 分かってるとは思うけど、デザパタ扱うなら、他にもっとパターンある事に気付よ。 あんま鈍い事やってると、コンポーネントを先駆けながらMVCに固執し過ぎて 時代のかなたに消え去ったなんちゃらパッドと同じ運命辿るぞ、と。
91 :
デフォルトの名無しさん :04/05/16 09:22
あ、ごめん、
>>89 はギリギリセーフかな。
元ネタがアレだから、全部トンデモに見えるw
92 :
デフォルトの名無しさん :04/05/16 09:46
ウソっぽい議論をさも意味ありげに続けてるカワイソウな人のスレ。 さっさと進化しる。
93 :
デフォルトの名無しさん :04/05/16 09:52
この手のスレはキモイ。 自分で問題を発見して解決する訓練をしてないリアル工房が、 他で聞いた意見や議論の切れっ端を、独自解釈して意味ありげに書き連ねるだけ。 議論は伸びても、一向にに問題は解決せず、 いつも識者が答えを書いてくれるのを待ってるだけ。 そーゆー無能でキモイ振る舞いが、カッコイイ、マニアックな知的活動 とか勘違いしてるんじゃねぇーの?
94 :
デフォルトの名無しさん :04/05/16 09:56
ここの
>>1 は、自分は、自分での問題意識を整理して主張する事すらできんクズ。
あんまかわいそうだから、
>>89 が
>>1 の問題意識を代弁してやった、と。
だけど
>>1 は馬鹿だから、決して
>>89 に感謝することは無いと思うよ。
>>89 が何言ってるのかすら、理解できてないと思う。
むしろ、一般人は
>>89 もトンデモな人なのか、と勘違いしちまうのがオチ。
>>90 が誤解したみたいにねw
95 :
デフォルトの名無しさん :04/05/16 09:57
ここの
>>1 は、自分の問題意識を自力で整理して主張する事すらできんクズ。
あんまかわいそうだから、
>>89 が
>>1 の問題意識を代弁してやった、と。
だけど
>>1 は馬鹿だから、決して
>>89 に感謝することは無いと思うよ。
>>89 が何言ってるのかすら、理解できてないと思う。
むしろ、一般人は
>>89 もトンデモな人なのか、と勘違いしちまうのがオチ。
>>90 が誤解したみたいにねw
>>93 スレの主旨に乗れないなら黙ってろクズが
ある提起された議論がすべて何かの解決を目的としたものなのか?
お前は
>>1 が何かを解決しようとしているように見えるのか?
思っていることを書き連ね、それに対し誰かが意見を言う
会話そのものが目的だということがわからんのか?
93=94=95
リアル工房の論争が見られるスレはここですか?
99 :
デフォルトの名無しさん :04/05/16 12:12
議論は伸びても、一向にに問題は解決せず、 いつも識者が答えを書いてくれるのを待ってるだけ。 そーゆー無能でキモイ振る舞いが、カッコイイ、マニアックな知的活動 とか勘違いしてるんじゃねぇーの?
↑ 2chで問題解決を求める低脳。
>>1 デザインパターンも全部委譲でやるの?
考えただけでウンザリなんだけど。
>101 それって委譲に関して、言語的に公開手段があれば問題ないってことかな?
103 :
デフォルトの名無しさん :04/05/16 13:06
>>100 しねはげでぶ。
>>102 ポリモルフィズムを型階層の外で実現しようつうのがジェネリックなわけだし、
継承をなんとかしようつうのは、皆意識してやってるよ。
継承を委譲の特殊なケースとして扱いながら、
委譲によるコーディング量増加を減らすための工夫もいろいろされてるだろ。
設計レベルなら、ステロタイプでstrategyとか指定してコード生成するとか、
リファクタリング・レベルなら、メソッドの外部クラス化とか。
>>101 ,102
ダブルディスパッチを伴う Visitor パターンは委譲だけでは書くことができないな。
Composite パターンで作ったオブジェクトのトラバース (構文木解析なんか) は異常に書きづらくなる。
プププ。背伸びして知ってる用語並べちゃって。w
106 :
103かきなおし :04/05/16 13:12
>102 ポリモルフィズムを型階層の外で実現しようつうのがジェネリックなわけだし、 継承をなんとかしようつうのは、皆意識してやってるよ。 たしかに継承を、データやメソッドの一部を共有したクラス間の 特殊な委譲?と見なすこともできるだろうけど、前提条件多過ぎて意味不明だ。 委譲によるコーディング量増加を減らすための工夫もいろいろされてるだろ。 設計レベルなら、ステロタイプでstrategyとか指定してコード生成するとか、 リファクタリング・レベルなら、メソッドの外部クラス化とか。
> 継承をなんとかしようつうのは、皆意識してやってるよ。 じゃあ、このスレで議論する余地はあるね。
> 前提条件多過ぎて意味不明だ。 意味不明なのは君の書き込み
109 :
デフォルトの名無しさん :04/05/16 13:14
むつかしいなあ
110 :
デフォルトの名無しさん :04/05/16 13:15
>>104 きみはいつもその例だすね。
ダブル・ディスパッチなんて、
クラス間の相互作用を調整し損なってる悪い例、
そりゃそれ使えばいろいろできるとはわかってるけど、
きちんとした設計では排除する例、って感じするけど。
で、どうしてもそれが必要なら、設計きちんとやる時間が無いとみなして、
多少の設計上の汚さには目をつぶっとくもんだ。
大体、Javaでパーサ書くって、ナニの仕事よ。
JavaCup使って言語処理系かよ。
> ナニの仕事よ オナニーの仕事
112 :
デフォルトの名無しさん :04/05/16 13:26
>>107 まぁね。でも
>>1 は、
「全部明示的なメソッド呼びだしで書けばいいやん」という趣旨の魅力に欠ける提案しかしていない。
新しいビジョン示さないと、誰も相手にしないよ、今更。
今のスタイルのOOが定着する前から続行している話題やん。
>>108 いみふめ。
要するに、型継承+実装継承を全部無視すりゃ、委譲しか残らないけど、
全然魅力的な提案じゃねぇや、COBOLerのおかしなコーディング規約聞いてるみたいで、片腹イタタ、って感じ。
113 :
デフォルトの名無しさん :04/05/16 13:31
>>104 たぶん、その例でそのパターン適用すること自体に、多少の無理があるんだろうな。
GoFって単なる博士論文の延長線上の仕事だろ。今の視点で見ると、いろいろ問題ある。
GoFは知ってても、その先の問題解決できないのは、ちょっと。
で、あんたのおっしゃること、なんとなくGoFのサンプルの例そのまんまの話じゃねぇ?
たとえば、今からある販売会社A社の会計システムをこれから作るよう命ぜられた。 A社の業務には冷凍食品の販売とタバコの販売があり、 冷凍食品とタバコの価格を計算する処理をこれから作らなければならない。 冷凍食品の価格には売値+消費税がかかる。 タバコの価格には売値+消費税+タバコ税がかかる。 しかしタバコ税にもいろいろあり 国タバコ税、地方タバコ税、タバコ特別税 などいろいろな計算処理がある 手続き型プログラムしか知らない人は、 まず消費税計算関数をごちゃごちゃつくり、 そのあとタバコ税計算関数をごちゃごちゃつくり、 あとでメインの関数でこれら関数をコールする。 これは非常に非効率だ。(たぶん) しかし継承を使ってプログラミングをすれば すべての税計算はクラスで一元化されており、 売値の値を格納しているクラスへ税計算クラスを継承させるだけで、 価格計算がもう終わっているとしてよいことになる。 それが継承を使う利点だ。 ただ、使える税計算クラスがまだ世に出てないことが問題なのだ。 ^^^^^
>>114 「継承を使ってプログラミングする=手続き型ではない」
って思っているの?
たとえば、今からある販売会社A社の会計システムをこれから作るよう命ぜられた。 A社の業務には冷凍食品の販売とタバコの販売があり、 冷凍食品とタバコの価格を計算する処理をこれから作らなければならない。 冷凍食品の価格には売値+消費税がかかる。 タバコの価格には売値+消費税+タバコ税がかかる。 しかしタバコ税にもいろいろあり 国タバコ税、地方タバコ税、タバコ特別税 などいろいろな計算処理がある 構造化技法しか使わない人は、 まず消費税計算関数をごちゃごちゃつくり、 そのあとタバコ税計算関数をごちゃごちゃつくり、 あとでメインの関数でこれら関数をコールする。 これは非常に非効率だ。(たぶん) しかし構造化技法を使わずにプログラミングをすれば すべての税計算はサブルーチン1つで一元化されており、 売値の値を計算した後、税計算部分にジャンプするだけで、 価格計算がもう終わっているとしてよいことになる。 それが構造化技法を使わない利点だ。 ただ、使える税計算サブルーチンがまだ世に出てないことが問題なのだ。 ^^^^^
>>117 そんなもん、構造化とか関係ない話ですね。
理想として継承はインタフェースに限定するという考えは理解できるが、実世界においては実装の継承が可能であった方が良いと思う。 以下に、その理由を示す。 実装の継承を認めない場合は、以下のようになる。 class IHoge; class HogeA : public IHoge; class HogeB : public IHoge; 実装の継承を認めない場合、HogeAに拡張を施す場合は以下のようになる。 class HogeA2 : public IHoge{ private: HogeA hoge_; }; ここで、HogeAか拡張されたHogeA2を場合により使い分けたいが、HogeBは使いたくないコードを書きたいとする。 インタフェースの継承しかないと、次のようになる。 std::auto_ptr<IHoge> pHoge = new HogeA; //又はnew HogeA2; これだと、インタフェースIHogeしか継承していないため、誰かが new HogeB とコード変行使してしまう可能性を排除できない。 排除するには、以下のようにHogeAのインタフェースも用意する必要がある。 class IHogeA : public IHoge; class HogeA : public IHogeA; class HogeA2 : public IHogeA{ private: HogeA hoge_; }; そうすれば、以下のようにIHogeAポインタを受け取るようにして、HogeBが利用される可能性を排除できる。 std::auto_ptr<IHogeA> = new HogeA; // 又はnew HogeA2; ただし、今後同じようなことがあった場合にインタフェースクラスを増やしつづけなくてはいけないという問題がある。 また、既に class HogeA : public IHoge となっている場合、仕事上では class IHogeA を作り class HogeA : public IHogeA とする事が困難な場合もある。 続く
続き 実装の継承が許されるなら、以下のように書くことは出来る。 class IHoge; class HogeA : public IHoge; class HogeB : public IHoge; class HogeA2 : public HogeA; std::auto_ptr<HogeA> pHoge = new HogeA; //又はnew HogeA2; この場合、class Hoge を書き換える必要性は無い。また、誰かが new HogeB としてHogeBが使われる可能性は排除できる。 ただし、std::auto_ptr<IHoge>と書き換えられると、HogeBが使われる可能性は出てくるのだが・・・。 その為、実際のプログラム環境においては、実装の継承も可能である事が望ましいと考える。
>>120 Hoge を書き換える必要性は無い
>> HogeA を書き換える必要性は無い
tamplate<T> class Hoge : public IHoge { private: T hoge_; } にしちゃあかんの?
std::auto_ptr<HogeA> pHoge を、std::auto_ptr<IHoge> pHogeに変更した場合、 new HogeBが有効になるというツッコミを予想して追加。 この場合、変数pHogeの意味が全く変わってしまいます。 std::auto_ptr<HogeA>というの文が、どういう意図を含むものか考えてください。
>>122 std::auto_ptr<IHoge> pHoge = new Hoge<HogeB>;が出来ちゃいません?
あと、C++でテンプレート禁止って開発環境も世の中にはあるんですよね・・・
>>124 今回はstd::auto_ptr使ってるから、テンプレートOK環境と考えるべきですね。
>124 開発環境の制限については、現場のルール次第なのでとりあえず今回の問題領域 じゃないですよね それを除けば、解決なんでしょうか?
委譲対象が自分と同じメンバ関数を持っていたら、自動的にそれを呼ぶような言語仕様にしてくれれば、 とりあえずポリモフィズムは克服できそうかな?
あ、流れを無視してごめん。 と思ったが、templateを使ってポリモフィズムすることも出来そうだな。と話を合成してみる。
>127 自動的だとメンバが衝突する可能性があるから何らかのキーワードは必要だろうけど、いいね C++ /CLI では、インターフェイスと提供する実装について、次のような指定方法が あるんだけど、これの委譲での振り分けみたいなものがあればいいのにねぇ interface IA { void f(); void g(); } interface IB { void f(); int h(); } ref class KlazzInpl : public IA, IB { virtual void f() = IA::f; virtual void g() = IB::f; virtual void fg() = IA::g; virtual int h() = IB::h; }
130 :
デフォルトの名無しさん :04/05/16 18:32
結局、OO継承における親クラスへのポインタを、 (実行時に動的に)他のクラスに切り替えられて、 しかも型安全性と両立するようなモデルを作れば終了だろ。 MITで、C言語ベースでオブジェクト機構をメタにいじくれる言語作ってたっけ。 (C++でもObjectiveCでもない) あれの流儀に近いんじゃないかな。
>>127 class Interface{
public:
virtual void method();
};
class Super: public Interface{
public:
virtual void method(){}
};
class Sub: public Interface{
Super super_;
public:
virtual void method(){ super_.method() }
};
int main(){
Interface* super = new Super;
Interface* sub = new Sub;
super->method();
sub->method();
}
オーバーライドするときは委譲しないことにすれば
↑でポリモルフィズムは克服できてると思うんだけど、
記述を楽に出来る構文があれば良いってことかな。
↓みたいな感じの構文があればいいのかな。
class Sub: public Interface{
Super super_;
public:
virtual void method() leaveto super_;
};
>>93 議論って言っても討論は問題の解決が目的じゃないと思うんだけど。
133 :
デフォルトの名無しさん :04/05/16 22:30
>>132 2ちゃんでは、ぐずぐずになって嵐が跳梁跋扈するケースが多いから、
たまには問題意識と目的意識を明確にしとくのも良いのではないか。
>>119 あるクラスはそのクラスのインターフェースを必ず継承しとかないと
いけないって規約だと駄目かな。
HogeAに対しては絶対に
class IHogeA: public IHoge, public OtherInterface{};
みたいなのがあるって前提で。
>>89 >1.
言語側に委譲構文を用意する。
>2.
privateなメソッドは現状でも普通に書ける。
protectedは・・・あるインターフェースを持ったクラスには
公開するようなメソッドが定義できれば良いのかな。
>3.
オブジェクトの数が増えるのはどうしようもないな。
逆にクラスの数は減るから管理しやすくなるってのもある。
>4.
集約とコンポジションを厳密に分けて、コンポジションの場合は
親オブジェクトと生存期間を共にするってことにすればいいんじゃないかな。
継承禁止、インターフェイスのみ、なんてのはそう組めばすむ話だから(virtual継承でもなんでもして作ればいい) それでいいじゃんと思ったり、 それはともかく、UML、あのクラス指向なのは何とかならんのかと思ったり。
>>136 >そう組めばすむ話だから
それ言ったら議論の生まれる余地がないよ
>それはともかく、UML、あのクラス指向なのは何とかならんのかと思ったり。 コラボレーション図みれ
C++ 前提でスレが進んでるみたいですが もともとクラスというものが存在しないプロトタイプベースの言語の存在についてはどう思われますか?
プロトタイプベースは使ったことがないからよくわからんのだけど、
クラスの概念は悪いものじゃない。
ただ、現在のクラスをベースにしてる言語の多くが
クラスと型をごっちゃにしてしまってるのは問題だと思う。
全然
>>140 に対する答えになってなくて悪い。
>>140 なかなか使いこなせない、templateと同じで、感触的にはまだ溶鉱炉から取り出したばかりの銑鉄的な感触だと感じる。
可能性を感じつつもバグの温床状態。
>>140 プロトタイプ・ベースは、
>>130 みたいな方向じゃないかな。
クラスじゃなく、オブジェクトを継承するという違いはあるけどね。
で、ここの
>>1 は、
最近2ちゃんで何故か盛り上がってるプロトタイピング・ベースのOO言語
の知識を持った上で、スレ立てしたんだと思う。
オチがプロトタイプ・ベースで終了、
というのは、ちょっと寂しい感じがするな、話題の発展方向として。
>>139 いみふめ。
じゃ、代替案を提示してみそ。
#クラスに偏重してるのって、クラス図しかないけどな〜
#
#もしかして、クラス図だけ使って全てを設計しようとするような、
#訳ワカラン事してるわけ、、、ないよね?
いや、MOF とか見てるとここまで良くやるわって気分になるぞ。
>>144 あれが書きやすいと思うのなら、OOを理解したつもりで迷走しとる思うね。
スモールトークを作った人もあれはオカシイと言ってますけど、オレはそれに賛成。
オブジェクトはあくまでインスタンスが中心であるべきだ、
クラスはインスタンスを効率よく生産する手段でしかない。
>オブジェクトはあくまでインスタンスが中心であるべきだ オブジェクト指向はあくまでインスタンスが中心であるべきだ の間違い
COM の集合みたいな構成はどうだろう? コンポーネントという複数のオブジェクトによって構成された実体に対してインターフェイスに よるアクセサで操作するような言語
それは使う側の話だろ。 インスタンス作って使うだけなら異常だろうと多重軽症だろうと関係ないし。
150 :
デフォルトの名無しさん :04/05/17 12:56
>>146 ふーん。情報ソース示してみそ。
俺、Smalltalk、15年前からやってるけど、
UML使うような仕事ではSmalltalkなんて使わないし、
世の中のOOビジネスの90%以上はSmalltalk以降の話で成り立ってるんだから、
別物と考えていいんじゃないの。
ClassがFirstClassのObjectの言語(Smalltalk)と、
ClassはObjectの雛形で、それにリフレクション後付けした言語(Java)じゃ、
そこらへんの随分解釈違うしね。
>>146 はずいぶん気張ったカキコをしてくれたけど、
別にオブジェクトの解釈に、唯一絶対の下意があるべきだとは思わない。
ただし、もし「単純なモデル」で「多くの事柄を説明」できかつ「実用的な対応を取りやすい」
そんな視点があるのなら、それは優れてると思うから、ぜひ紹介してね
>ふーん。情報ソース示してみそ お前友達いないだろう 教えてやらん、わりと著名な日本語のページにあるから必死こいて自分で探せ。
>>153 ハタから見ると、
>教えてやらん、わりと著名な日本語のページにあるから必死こいて自分で探せ。
お前の方が友達いないんじゃないかと思うなあ。
>>152 は、なにいいたいのか良くわからん。
なんか良いアイデアあるなら、あっちのスレにも書いてね(♥
良スレ
>>151 それ>26は単なる笑えない冗談だろ。
見事釣られたわけだねw
>>126 std::auto_ptr<IHoge> pHoge = new Hoge<HogeB>;
って感じで、ある枝のパターンを防げないって事を除けばtemplateでOKだと思う。
>>134 それやってしまうと、クラス数が爆発して大変じゃないかなぁ?
クラスに対して、自動的にインタフェースを作ってくれる構文があれば便利なんだが。
class HogeA : __interface;としておくと、
std::auto_ptr< IHogeA > pHogeA( new HogeA );
って感じでIHogeAが出てきた時点で、言語レベルでHogeAから
インタフェースクラスIHogeAを準備してくれるとか。
>>159 追加説明
class HogeA : __interface, public IHoge, public OtherInterface{};
ってクラスがあれば、
std::auto_ptr<IHogeA> pHogeA( new HogeA );
としたときには、
class IHogeA : public IHoge, public OtherInterface{};
が自動的に作られるような構文があればなぁって事ね。
>>148 スレの内容に対して、その内容がどう絡んでいるのか判らないのだが・・・
余談
UMLって、初期はコミュニケーション言語的な使われ方だったと記憶してるんだが、
いつのまにかプロジェクト資料として残す設計言語って感じになってきてるよね・・・
以前の、不完全な使われ方だけど、設計の大筋が伝わるって頃の方が好きだったなぁ。
>>159-160 Hogeに対してIHogeが必ず対で存在することを保障するなら、
管理は別に難しくないんじゃないかな。
まあ
>>160 みたいな構文があれば記述が楽になることは確かだと思う。
164 :
デフォルトの名無しさん :04/05/18 01:04
>>161 いみふめ。
昔はそーだったんですか。
あと、現在の方も?
今は、「プログラミング言語のソースを自動生成可能な設計データ」
と見なされつつあるのかと、思ってたあるよ。
>>162 まあ、クラス数が増えるだけで管理は可能ですね。
クラスのヘッダファイルに、コピペ使ってインタフェース専用クラスも用意すればいいか。
>>164 もちろん、設計データとしての側面も以前からあるけど、
より良い設計を実現する為のコミュニケーションツールとしての側面は
昔の方が強かったなぁっと思ったのですよ。
設計データ作成と称して、誰とも会話せずに黙々と図を書いてる人とか見ると、
なんか使い方がおかしくなってるんじゃないかなぁっと感じたり・・・歳か!?
166 :
デフォルトの名無しさん :04/05/18 08:26
C++で比較的少数で開発してましたが、シーケンス図やインスタンス関連図(クラスの関係でなく,場合場合におけるインスタンスの全体的な関係)を使ってました.純粋なUMLは無駄で使えない. まぁ大規模開発ではそういかないんだろうけど. 全体としてはソース,クラス,シーケンス,仕様(文書)などのシームレスなツールを所望するがいまだない...
>161 なんか、スレの内容とはあまり関係のないUMLの話が出てきて謎なんだが、 >148 は 委譲ではなく集合の概念で継承を回避してはどうかという話だと思われ
169 :
デフォルトの名無しさん :04/05/18 22:41
C++以外では多重継承がNGってことからも 継承自体のアンチ論が出ても不思議じゃないな 俺も派生の派生ってのだけは、絶対にやらないし
171 :
デフォルトの名無しさん :04/05/18 22:55
>>168 おぉ、随分古い記事引っ張り出してきたね。
たしか、プレi-αppLi時代 (ドキュモx503i以前) の記事じゃなかったっけ。
172 :
デフォルトの名無しさん :04/05/18 22:59
>>170 クラス階層は2階層まで派、ですか。
こりゃまた厳しい。Interviewの中の人は、3階層まで派だっけ。
俺は、汎用クラスは結構深くてもおっけ(但し全部深いのは勘弁)派だなw
173 :
デフォルトの名無しさん :04/05/18 23:00
>>172 基底>派生>派生だと、真ん中の派生クラスが何か気持ち悪いんだよ
お前は一体何したいの?みたいな気分になる
しかし例外的に抽象>派生>派生ならその嫌悪は無い
趣味グラマの希望の星D言語では void hogeMethod(HogeClass hc){} と定義しとくと、継承なしに HogeClass hc = new HogeClass(); hc.hogeMethod(); とできるらしい
Eiffelは多重継承マンセー
CLOSも多重継承可能だな
>173 集合は言葉が正しくないな。集成 (Aggrigation) だわ
179 :
デフォルトの名無しさん :04/05/19 00:32
.net が多重継承だめなのは至極残念
180 :
仕様書無しさん :04/05/19 00:35
181 :
デフォルトの名無しさん :04/05/19 00:41
いや多重継承マンセー派なので グルーコード書くのめんどくさくて嫌い
全部コンポジションにすりゃいいじゃんって意見は分かりやすくて好きだがな ポリモフィズムを必要とするプログラムって、それでなくても組めるし
183 :
デフォルトの名無しさん :04/05/19 00:51
>>182 ポリモルフィズムって、要するにパラメータでディスパッチができれば
いいだけのことだもんね。
そんなのCの頃だって関数ポインタテーブルでやってたしぃ。
>>182 論点ずれてない?
実装継承はいろいろ問題があるからコンポジションにしようってのが
このスレの話の流れだと思うんだが。
>>185 おまえがずれてるだろ。
この話の流れは
>>1 全部コンポジションでいいじゃないか(問題提起)
-> プッ勉強不足だな継承は必要なんだよ(大勢)
-> 雑談
->
>>182 >>1 の考えはわかりやすくて好きだ(1に賛同する少数派)。
どうしても継承をしたいとなると、スーパークラスは派生クラスを作った後で決めたい そもそも抽象化とは数多くあるクラスの共通の機能を抽出する行為なのに プログラマがしなければならない思考の順序がプログラムの作成順序とは逆で 雑多なクラスを作る前に、共通機能を決めなければならない、 だからせっかく作ったライブラリが歪む事になる。 これが恩恵は少なく弊害は多い理由だと思う、 が、STLやらboostやら見ていると改善余地はあるかなと思ったりもする。 クラス継承は使わなくてもすむなら使わないに越した事はないが、言語機構的に無くされるとちと困る。 少なくともgotoが無いと困る程度には困る。
・基底→派生 ・抽象→基底(いやこれも派生だけどね)→派生 これが人が無理なく管理できる継承ネストの目安かと
>>187 >どうしても継承をしたいとなると、スーパークラスは派生クラスを作った後で決めたい
この案はいいな。
トリッキーでなく実現可能な言語ってあったりするの?
190 :
デフォルトの名無しさん :04/06/03 12:58
>>189 「(抽象)基底クラスの抽出」ってフレーズを、
聞いた事ありません?
191 :
デフォルトの名無しさん :04/06/07 22:35
ageますね
プラットフォームに合わせてインタフェース弄くる程度の横に長い派生くらいしか使わない
Cで無理やりOOするのはしんどくて空しくて効率悪いのと同様に 言語に備わってないことを無理やりやるのは好きじゃないね。 特に委譲しまくりはめんどい。 何事もほどほどにバランスよく好き嫌いせずに使っとけ。
>>193 って、何か含蓄のある発言に見えるけど、
その実は
「俺の方法が1番、俺と同じようにやれ」
と言っているのと同じことだったりして。
おまえは「ひまわり」や「TTSネオ」も
バランスよく使っているのかと小一時間問い詰めたい。
バランスよく使うと、比率が0になりますた。
196 :
デフォルトの名無しさん :04/06/10 12:57
アフォはだれにも相手にされず、自分で突っ込むより他の術がないのねw
>>195 つまり、「自分(の基準)が一番バランスが良い」という訳で。。。
(´,_ゝ`)
199 :
デフォルトの名無しさん :04/08/15 19:22
◇◇◇ ひし形最強!! ◇◇◇
●● 200最強!! ●●
うんこ
>>199 でもあんたそれ正方形ですからー
残念!!
小3からやり直せー斬り!!
ぽかーん
「ジョンは動物じゃないよ!犬なんだよ!!!」って力説するタイプ
クラス設計について語るスレはここですか?
海面下730mの海底に達した。
207 :
デフォルトの名無しさん :05/02/15 12:37:48
>>206 >海面下730mの海底に達した。
何が?
スレ一覧の一番下に来たってこと。
適当に読んでみたけど、難しいな。 泣きそう。
新たに機能を作るのが面倒ってんで、既存の別機能のクラスを継承して作ることになりますた。 確かに当面の面倒はないが、まったく関係ない余分な機能やらincludeファイルやらを抱え込むことに… 犬から猫を派生させたみたいになりそうなんですが、 実務だとこういう手段がとられることって結構あるんですか?
>>210 ない。機能面から設計してる時点であぼーん。
>>210 このように使われるから
>>1 みたいなのが出てくるってコトね
全く関係ない余分な機能やらってオワットル
ありゃオレちょっとぼけてる。 本当は機能面じゃなくて実装面って書きたかったのです。
>>210 もし継承したいんなら、その共通する機能で別のくくりができるだろうから
それだけ切り出した方がまだイイと思うぞ。
つーか継承する必要なさそうな予感
安易な継承は、グダグダなソースを産む元
C++コミュニティに言わせると javaそのものがアンチパターンのようだ
おおよそメソッド4つ以上をコンポジションしようとしたらダルいっすよ アジャイルじゃねえよ。継承させろよ。適度に弁えて使うからさあ。
>>216 "Modifier Class Template"でググれ
218 :
デフォルトの名無しさん :2005/04/06(水) 19:35:38
class inter { public: virtual void method() = 0; }; class super_super : public inter { public: virtual void method(); }; class super : public inter { private: super_super *ss; public super() : ss(new super_super) {} public ~super() { delete ss; } public: virtual void method() { ss->method(); additional_process(); }; class self : public inter { private: super *s; public self() : s(new super) {} public ~self() { delete s; } public: virtual void method() { s->method(); additional_process2(); }; interface継承だけで、2段階の実装継承を委譲で実現するとこんなかんじ コンストラクター起動で、newが二回余分に走るw method()呼んだときに余分に生じるポインタ参照はいくつだ? 効率的に終わってるよ
誰もそんな話してないのでは?