ページ 1 / 1
クラス間の変数のやり取りについて
Posted: 2012年7月05日(木) 00:43
by Fimbul
質問を修正したので、No.8(88503)を参照してください。
例えば、下記の図のクラス構造を考えます。
図で、保持と言うのはインスタンスの保持です。
クラスA←←←
↑ ↑
↑保持 ↑保持
↑ ↑
クラスB クラスC
↑
↑保持
↑
クラスD
クラスBとクラスC間のメンバ変数のやり取りは、クラスAが両方のインスタンスを保持しているので、簡単に行えると思います。
では、例えばクラスBとクラスD間の様な遠い距離にあるクラス間のメンバ変数のやり取りは、どの様な方法が最適なのでしょうか。
例えば、クラスBのメンバ変数をクラスDに渡す場合、
1.クラスBで対象のメンバ変数をシングルトンクラスに渡す。
2.クラスDでシングルトンクラスから受け取る。
とすれば可能ですが、オブジェクト指向プログラミング的で無い感じ?がします。
シングルトンクラスは、例えば、ゲームのキーボード処理、画像ハンドル受け渡し処理等、どこからでも呼び出せないと困る処理のみ使用すべきであり、単にメンバ変数のやり取りに使うべきでないと思いました。
同じくクラスBのメンバ変数をクラスDに渡す場合、別の方法として、
1.クラスAがクラスBのメンバ変数を受け取る。
2.クラスAがクラスCにそのメンバ変数を渡す。
3.クラスCがクラスDにそのメンバ変数を渡す。
この様にバケツリレーの様な感じで可能ですが、クラスA、Cがそのクラス自体に関係の無い処理を含む事になり、適切なクラス設計でないと思います。
Re: クラス間の変数のやり取りについて
Posted: 2012年7月05日(木) 01:37
by nullptr
まず、「保持」について確認ですが
> クラスAが両方の
インスタンスを保持しているので
ということは、BとCがAに
包含されているという解釈で良いのでしょうか?
それともインターフェイスを保持しているのでしょうか?
まあそれはそれとして、Bのメンバ変数をDに渡す方法がいくらでもあるのはわかると思います。
そのうちどうやって渡すのが良いかというのはケースバイケースだと思います。
ただ、オブジェクト指向的にやるとして一般的なの方法はBのインターフェイスをDに渡す方法ではないでしょうか。
渡したい変数がint型targetという仮定で例えのコードを描くなら、
コード:
class InterfaceB
{
public:
virtual int getHensuu() const = 0;
};
class B
:public InterfaceB
{
//例えなのでいろいろ省略します
int target;
public:
int getHensuua() const{ return this->target; }
};
とし、A経由なりC経由なりで一回InterfaceB*型に格納したBのポインタをDに渡せば良いのではないでしょうか。Dはメンバ変数なりで保持すれば良いと思います。
> クラスA、Cがそのクラス自体に関係の無い処理を含む事になり
もし変数を直接バケツリレーするならそうでしょうね。
ただ先程のようにBのインターフェイスをコンストラクタなりで渡してしまえばそれでオッケーです。
コード:
// ※コンストラクタで渡す例
class A
{
B b;
C c;
public:
A():b(),c(&b){}
};
class C
{
D d;
public:
C( InterfaceB* b ):d( b ){}
};
class D
{
InterfaceB* i;
public:
D( InterfaceB* b ):i( b ){}
void test(){
int a = this->i->getHensuu(); // Bのメンバ変数targetの取得
}
};
Re: クラス間の変数のやり取りについて
Posted: 2012年7月05日(木) 08:12
by Fimbul
新月獅子 さんが書きました:
ということは、BとCがAに包含されているという解釈で良いのでしょうか?
はい、継承ではなく包含です。
新月獅子 さんが書きました:
ただ、オブジェクト指向的にやるとして一般的なの方法はBのインターフェイスをDに渡す方法ではないでしょうか。
インターフェイスで渡せば、インターフェイスのメンバ関数しか呼べないので、余計な情報を公開する事は無く、隠蔽出来ていると言えると思います。
ですが、コンストラクタ経由で渡しても、クラス間の距離が今回よりも遠い場合は、リレーが長くなって結局汚いコードになってしまうと思います。
インターフェイスをシングルトンクラスに渡せば、どこからでもそのインターフェイスにアクセス出来ますが、必要なインターフェイスを全てシングルトンクラスに押し込める構造になり、良くない設計になってしまいます。
Re: クラス間の変数のやり取りについて
Posted: 2012年7月05日(木) 16:33
by nullptr
今回のAやBなどの抽象的な例えで、それらがどういう目的や関係性なのか、Bのメンバ変数がどういう目的、範囲で使用されるかもわからないのですから、こちらは一案を提示するしか無いわけですが。
> ですが、コンストラクタ経由で渡しても、クラス間の距離が今回よりも遠い場合は、リレーが長くなって結局汚いコードになってしまうと思います。
知りません。
リレーが長くなっても、たとえ汚くなっても、それが正しい設計の場合だってあると思います。
BやDそれぞれのクラスの役割や依存の仕方がわからない以上、私にはそれを判断することはできません。
ただ、今回DはBの情報を知りたいわけです。この時、実装はともかくDはBに関係する必要があるわけです。
そのひとつの方法としてコンストラクタリレーを上げましたが、設計的に正しくないと思ったなら他にも方法はあると思います。
例えばBとDの橋渡しとなるクラスを作るとか。
オフトピック
これも具体的なクラスの情報がわからないのであんま言えませんが、こんな包含でガッチガチな関係の設計で大丈夫ですか
Re: クラス間の変数のやり取りについて
Posted: 2012年7月05日(木) 23:11
by Fimbul
出来るだけ多くの意見を聞きたいので、他の方の回答もお待ちしています。
Re: クラス間の変数のやり取りについて
Posted: 2012年7月05日(木) 23:59
by トントン
Fimbul さんが書きました:新月獅子 さんが書きました:
ということは、BとCがAに包含されているという解釈で良いのでしょうか?
はい、継承ではなく包含です。
新月獅子 さんが書きました:
ただ、オブジェクト指向的にやるとして一般的なの方法はBのインターフェイスをDに渡す方法ではないでしょうか。
インターフェイスで渡せば、インターフェイスのメンバ関数しか呼べないので、余計な情報を公開する事は無く、隠蔽出来ていると言えると思います。
ですが、コンストラクタ経由で渡しても、クラス間の距離が今回よりも遠い場合は、リレーが長くなって結局汚いコードになってしまうと思います。
インターフェイスをシングルトンクラスに渡せば、どこからでもそのインターフェイスにアクセス出来ますが、必要なインターフェイスを全てシングルトンクラスに押し込める構造になり、良くない設計になってしまいます。
>クラス間の距離が今回よりも遠い場合は、リレーが長くなって結局汚いコードになってしまうと思います。
となると、外部変数(シングルトン)で参照しあえば良いのかなと思いますけどね。
後は設計の見直しでしょうか。
クラスD(またはクラスB)でやりたい機能がでかすぎてないか。細分化できないか。
本当に依存しないといけないのか。
など考えます。
ちなみに僕ならこのような設計になってしまって個人で作るなら、シングルトンで管理します。
まぁ、本当に大規模なプログラムを作ったことがないから簡単に言ってますけどね。
Re: クラス間の変数のやり取りについて
Posted: 2012年7月06日(金) 00:36
by softya(ソフト屋)
単純にクラスCからクラスDのインスタンスを得てクラスBに渡してはダメなのでしょうか?
なんなら機能制限したクラスEをクラスDの基底クラスにしてクラスEとして渡すという手もありますが。
Re: クラス間の変数のやり取りについて
Posted: 2012年7月06日(金) 09:37
by Fimbul
質問の内容を修正します。
クラスAとクラスBがあり、互いに遠い距離にあるとします。
これらのクラス間で各々のメンバ変数をやり取りする場合、どのような方法が最適なのでしょうか。
そもそも遠い距離にあるクラス間に関係がある設計がおかしいのかも知れませんが、どうしてもそうなってしまったと仮定してください。
補足として私が知っている方法は、
1.Mediator pattern
http://www.geocities.jp/ky_webid/design ... n/020.html
2.Singleton pattern
http://www.geocities.jp/ky_webid/design ... n/009.html
の2つです。
1番目の方法は、サイトを見ても完全に理解出来なかったので、この方法が最適なら詳しく教えてほしいです。
softyaさんにお聞きします。
プロならこうする、と言う方法を可能なら教えてもらいたいです。
Re: クラス間の変数のやり取りについて
Posted: 2012年7月06日(金) 11:01
by softya(ソフト屋)
デザインパターンで解決できるものでは無い気がします。
私としては、共有する必要性のあるデータを保持する別のクラスを作るが無難な気がします。
※ 仕事でC++を使っていた時にデザインパターンを使うような仕事をしていないので、プロとしてのコメントとしてご期待に添えないかも知れません。
Re: クラス間の変数のやり取りについて
Posted: 2012年7月06日(金) 13:11
by Ryo
何を引き出したいのかわからないけど
「具体的には何もありませんが、”よくある解決法では解決しない(恰好悪いので)”という状況があったとします。
これを解決するための、プロが使うようなカッコイイ最適解はありますか?」
って聞いてるように見える
Re: クラス間の変数のやり取りについて
Posted: 2012年7月06日(金) 15:44
by Fimbul
softya(ソフト屋) さんが書きました:
共有する必要性のあるデータを保持する別のクラスを作るが無難な気がします。
共有するデータを保持するクラスのインスタンスは2つのクラスから参照できて、かつ必要な間ずっと存在してなければならないですよね?
これをどうやって実現するのでしょうか。
Re: クラス間の変数のやり取りについて
Posted: 2012年7月07日(土) 00:03
by ISLe
Fimbul さんが書きました:共有するデータを保持するクラスのインスタンスは2つのクラスから参照できて、かつ必要な間ずっと存在してなければならないですよね?
これをどうやって実現するのでしょうか。
2つのクラスが、それぞれshared_ptrで、共有するデータを保持するクラスのインスタンスへのポインタを保持したら良いのではないでしょうか?
Re: クラス間の変数のやり取りについて
Posted: 2012年7月07日(土) 20:39
by Fimbul
ISLe さんが書きました:
2つのクラスが、それぞれshared_ptrで、共有するデータを保持するクラスのインスタンスへのポインタを保持したら良いのではないでしょうか?
共有するデータを保持するクラスのインスタンスを、離れた2つのクラスにどの様に渡せばよいのでしょうか。
Re: クラス間の変数のやり取りについて
Posted: 2012年7月07日(土) 23:17
by softya(ソフト屋)
Fimbul さんが書きました:ISLe さんが書きました:
2つのクラスが、それぞれshared_ptrで、共有するデータを保持するクラスのインスタンスへのポインタを保持したら良いのではないでしょうか?
共有するデータを保持するクラスのインスタンスを、離れた2つのクラスにどの様に渡せばよいのでしょうか。
mainから最初に渡せば良いのでは。
Re: クラス間の変数のやり取りについて
Posted: 2012年7月08日(日) 00:31
by ISLe
Fimbul さんが書きました:共有するデータを保持するクラスのインスタンスを、離れた2つのクラスにどの様に渡せばよいのでしょうか。
Abstract Factoryパターンというほどたいそうなものでなくて良いのですが、共有するデータを保持するクラスのインスタンスを引き出す関数とかを用意すれば良いのでは?
グローバルにアクセスできてしまうのが気持ち悪いのならば、コンテキストとしてクラス間でリレーするオブジェクトを用意して、そこに含める形になると思います。
Re: クラス間の変数のやり取りについて
Posted: 2012年7月11日(水) 21:32
by Fimbul
返信まで時間をください。
Re: クラス間の変数のやり取りについて
Posted: 2012年9月08日(土) 14:55
by Fimbul
ISLe さんが書きました:
Abstract Factoryパターンというほどたいそうなものでなくて良いのですが、共有するデータを保持するクラスのインスタンスを引き出す関数とかを用意すれば良いのでは?
グローバルにアクセスできてしまうのが気持ち悪いのならば、コンテキストとしてクラス間でリレーするオブジェクトを用意して、そこに含める形になると思います。
すみません。私には理解できませんでした。
「遠い距離にあるクラス間に関係がある設計」は、オブジェクト指向の設計として好ましいものなのでしょうか。
Re: クラス間の変数のやり取りについて
Posted: 2012年9月08日(土) 16:32
by ISLe
Fimbul さんが書きました:「遠い距離にあるクラス間に関係がある設計」は、オブジェクト指向の設計として好ましいものなのでしょうか。
好ましいかどうかは分かりませんが、特にハードウェア絡みだといきなりアクセスする準備ができていない場合があって、コンテキストを介したアクセスをするように設計せざるを得ない場合があります。
使う側からしたら面倒くさいですが、初期化のタイミングを制御できるメリットがあります。
例えば、Win32 APIのDCとか、Java(AWT)のGraphicsとか、AndroidのContextとか。
これらを用意するのはシステム側ですが、システムとアプリケーションの関係はそのままアプリケーション内部の実装に応用できると思います。
古い話ですが、BREWアプリがもろにコンテキストをリレーしないとほとんどのAPIにアクセスできないシステムでした。
なのでコアクラスというかアプリケーションクラスが必ず中心にあってシステムAPIもそのメンバ関数として実装するようにしてました。
Re: クラス間の変数のやり取りについて
Posted: 2012年9月09日(日) 09:03
by へにっくす
Fimbul さんが書きました:「遠い距離にあるクラス間に関係がある設計」は、オブジェクト指向の設計として好ましいものなのでしょうか。
好ましいかどうかは状況によるし、どう使うかによっても変わる。そもそも全然好ましくないのなら、デザインパターンとして出てこないのでは?
少なくとも2つのクラスを仲介する専用のクラスを作っとけば、片方の仕様が変わった時は、その片方のクラスと仲介クラスをみればいいのだから、十分じゃないの?
個人的には上の条件が満たせればいいと思っています。
(^^;
Re: クラス間の変数のやり取りについて
Posted: 2012年9月09日(日) 11:19
by nullptr
Fimbul さんが書きました:ISLe さんが書きました:
Abstract Factoryパターンというほどたいそうなものでなくて良いのですが、共有するデータを保持するクラスのインスタンスを引き出す関数とかを用意すれば良いのでは?
グローバルにアクセスできてしまうのが気持ち悪いのならば、コンテキストとしてクラス間でリレーするオブジェクトを用意して、そこに含める形になると思います。
すみません。私には理解できませんでした。
「遠い距離にあるクラス間に関係がある設計」は、オブジェクト指向の設計として好ましいものなのでしょうか。
他の方も返信されてますように好ましいかはその時々です。ただ、遠くたって正しい設計の場合はあると思います。
それと前々の返信から見ていて変数(コンテキスト)等のリレーがそんなに嫌なんでしょうか。
また、質問を修正してから「どうしたらよいのですか」の一点張りになっていますよ
Fimbul さんが書きました:
共有するデータを保持するクラスのインスタンスを、離れた2つのクラスにどの様に渡せばよいのでしょうか。
Fimbul さんが書きました:
共有するデータを保持するクラスのインスタンスは2つのクラスから参照できて、かつ必要な間ずっと存在してなければならないですよね?
これをどうやって実現するのでしょうか。
宿題ではないでしょうが丸投げ状態です。
もし手も足も出ていないというなら、デザインパターンやら綺麗な設計やらに手を出すのが早いか、間違いなのではないでしょうか。(私にはそうも見えませんが)
Re: クラス間の変数のやり取りについて
Posted: 2012年9月09日(日) 13:28
by Fimbul
新月の獅子 さんが書きました:また、質問を修正してから「どうしたらよいのですか」の一点張りになっていますよ
Fimbul さんが書きました:
共有するデータを保持するクラスのインスタンスを、離れた2つのクラスにどの様に渡せばよいのでしょうか。
Fimbul さんが書きました:
共有するデータを保持するクラスのインスタンスは2つのクラスから参照できて、かつ必要な間ずっと存在してなければならないですよね?
これをどうやって実現するのでしょうか。
宿題ではないでしょうが丸投げ状態です。
もし手も足も出ていないというなら、デザインパターンやら綺麗な設計やらに手を出すのが早いか、間違いなのではないでしょうか。(私にはそうも見えませんが)
勉強しても分からない事を質問する事と、丸投げは違います。
荒らしが目的なら私は返信はしませんし、最悪の場合は管理人さんに荒らしの処理をしてもらいます。
ISLe さんが書きました:Fimbul さんが書きました:「遠い距離にあるクラス間に関係がある設計」は、オブジェクト指向の設計として好ましいものなのでしょうか。
好ましいかどうかは分かりませんが、特にハードウェア絡みだといきなりアクセスする準備ができていない場合があって、コンテキストを介したアクセスをするように設計せざるを得ない場合があります。
使う側からしたら面倒くさいですが、初期化のタイミングを制御できるメリットがあります。
例えば、Win32 APIのDCとか、Java(AWT)のGraphicsとか、AndroidのContextとか。
これらを用意するのはシステム側ですが、システムとアプリケーションの関係はそのままアプリケーション内部の実装に応用できると思います。
古い話ですが、BREWアプリがもろにコンテキストをリレーしないとほとんどのAPIにアクセスできないシステムでした。
なのでコアクラスというかアプリケーションクラスが必ず中心にあってシステムAPIもそのメンバ関数として実装するようにしてました。
C/C++しか知らないので全部の理解は出来ませんでしたが、そう設計せざるを得ない場合がある事は分かりました。
へにっくす さんが書きました:Fimbul さんが書きました:「遠い距離にあるクラス間に関係がある設計」は、オブジェクト指向の設計として好ましいものなのでしょうか。
好ましいかどうかは状況によるし、どう使うかによっても変わる。そもそも全然好ましくないのなら、デザインパターンとして出てこないのでは?
少なくとも2つのクラスを仲介する専用のクラスを作っとけば、片方の仕様が変わった時は、その片方のクラスと仲介クラスをみればいいのだから、十分じゃないの?
個人的には上の条件が満たせればいいと思っています。
(^^;
確かにそうですね。
設計の問題でもあるかもしれないし、コーディングの問題でもあるかもしれないし、しかしながら、一般的に(少なくとも)仲介するクラスで解決すれば十分であるのかもしれまんせんね。
経験を積めば、状況に応じて適切な方法を使い分けられるようになるのかもしれません。
トピックが長くなりましたが、返答してくださった方どうもありがとうございました。
Re: クラス間の変数のやり取りについて
Posted: 2012年9月09日(日) 15:09
by ISLe
Fimbul さんが書きました:ISLe さんが書きました:例えば、Win32 APIのDCとか、Java(AWT)のGraphicsとか、AndroidのContextとか。
これらを用意するのはシステム側ですが、システムとアプリケーションの関係はそのままアプリケーション内部の実装に応用できると思います。
古い話ですが、BREWアプリがもろにコンテキストをリレーしないとほとんどのAPIにアクセスできないシステムでした。
なのでコアクラスというかアプリケーションクラスが必ず中心にあってシステムAPIもそのメンバ関数として実装するようにしてました。
C/C++しか知らないので全部の理解は出来ませんでしたが、そう設計せざるを得ない場合がある事は分かりました。
「分かった」というのは実際にそういうプログラムを作ってみて設計思想を理解したということですかね。
例として出したものは同列で、どれかひとつ理解できれば十分なので、C/C++しか知らなくても問題ありません。
考え方を理解できれば良いわけなので。
「C/C++しか知らないので全部の理解は出来ません」という言葉からは、端から理解する意思がないというふうに感じられます。
個人的には、実践しないで質問を繰り返すことも丸投げだと思います。
コンテキストの設計そのものに注目して欲しいので言語には関係ないと思うのですがね。
Fimbulさんは、「情報を引き出して使う」(コンテキスト内のデータにアクセスする)という考え方に固執しているように感じられます。
だからリレーすると汚いと。
Re: クラス間の変数のやり取りについて
Posted: 2012年9月09日(日) 15:52
by Fimbul
ISLe さんが書きました:「分かった」というのは実際にそういうプログラムを作ってみて設計思想を理解したということですかね。
例として出したものは同列で、どれかひとつ理解できれば十分なので、C/C++しか知らなくても問題ありません。
考え方を理解できれば良いわけなので。
「C/C++しか知らないので全部の理解は出来ません」という言葉は、端から理解する意思がないというふうに受け取れます。
「C/C++しか知らないので全部の理解は出来ません」というのは、そういう意味で書いたのではなく、せっかく書いていただいたのに全部理解できず、申し訳ないというニュアンスです。
「例として出したものは同列で、どれかひとつ理解できれば十分なので、C/C++しか知らなくても問題ありません。」
との事ですが、返信をもらった側は全部を理解しようとします。
ですので、例えば、Java(AWT)のGraphics、AndroidのContext、Brewアプリと言った言葉は私は初めて聞くので、調べて理解しようとする訳ですが、実際にプログラムを作れないので読んだ程度の理解になる訳です。
返信をした時点で、
「例として出したものは同列で、どれかひとつ理解できれば十分なので、C/C++しか知らなくても問題ありません。
考え方を理解できれば良いわけなので。」
というISLeさんの意思を私が読み取れなかったので、全部理解できず申し訳ないですという意味で書きました。
ですので、
「C/C++しか知らないので全部の理解は出来ません」という言葉は、端から理解する意思がないというふうに受け取れます。
というのは誤解です。
ISLe さんが書きました:個人的には、実践しないで質問を繰り返すことも丸投げだと思います。
このトピックを立てる時も、自分で出来る範囲での試行錯誤をしています。
そしてトピックで質問をして、返信をもらう訳ですが、理解できなければ実践も出来ません。
Re: クラス間の変数のやり取りについて
Posted: 2012年9月09日(日) 17:55
by nullptr
オフトピック
Fimbul さんが書きました:ISLe さんが書きました:個人的には、実践しないで質問を繰り返すことも丸投げだと思います。
このトピックを立てる時も、自分で出来る範囲での試行錯誤をしています。
そしてトピックで質問をして、返信をもらう訳ですが、理解できなければ実践も出来ません。
Fimbul さんが書きました:新月の獅子 さんが書きました:また、質問を修正してから「どうしたらよいのですか」の一点張りになっていますよ
Fimbul さんが書きました:
共有するデータを保持するクラスのインスタンスを、離れた2つのクラスにどの様に渡せばよいのでしょうか。
Fimbul さんが書きました:
共有するデータを保持するクラスのインスタンスは2つのクラスから参照できて、かつ必要な間ずっと存在してなければならないですよね?
これをどうやって実現するのでしょうか。
宿題ではないでしょうが丸投げ状態です。
もし手も足も出ていないというなら、デザインパターンやら綺麗な設計やらに手を出すのが早いか、間違いなのではないでしょうか。(私にはそうも見えませんが)
勉強しても分からない事を質問する事と、丸投げは違います。
荒らしが目的なら私は返信はしませんし、最悪の場合は管理人さんに荒らしの処理をしてもらいます。
理解できないならまだ考えるのは早いのでは、という返信へ何故こういう煽りが返って来るのか。失礼な方ですね。
Re: クラス間の変数のやり取りについて
Posted: 2012年9月09日(日) 18:06
by softya(ソフト屋)
穏やかにお願いしますね。
みなさんは、荒らしではないですよ。
Fimbulさんの試行錯誤の過程が見えないので、丸投げという印象を持った人が居たってことを理解していただければ良いかと思うのですが如何でしょうか?
今までの内容を整理して実験してみたこと、理解できないこと、疑問に思っていることを書かれてはどうでしょうか?
Re: クラス間の変数のやり取りについて
Posted: 2012年9月09日(日) 23:17
by ISLe
Fimbul さんが書きました:ISLe さんが書きました:個人的には、実践しないで質問を繰り返すことも丸投げだと思います。
このトピックを立てる時も、自分で出来る範囲での試行錯誤をしています。
そしてトピックで質問をして、返信をもらう訳ですが、理解できなければ実践も出来ません。
なるほど。
「全部の理解は出来ませんでした」からどんなニュアンスを読み取ったとしても、わたしの返信を読んだということ以外は分かりませんでしたが。
そういうことであれば、理解できるまで試行錯誤を頑張ってください、とだけ申し上げておきます。
これ以上余計なことを書くのは良くないと思いますので、必要なことは行間から汲み取っていただければ幸いです。