DOBON.NET DOBON.NETプログラミング掲示板過去ログ

基本フォームと派生フォームでの設定内容統一方法について

環境/言語:[[環境:WindowsXP Pro、使用言語:C#、.NetFrameWork:3.5]]
分類:[.NET]

いつも参考にさせて頂いております。

複数フォームにて重複した共通部分があるため、以下サイトを参考に基本フォームを作り、継承機能を活用しようと思っております。
【参考サイト】
http://www.atmarkit.co.jp/fdotnet/dotnettips/324winbaseform/winbaseform.html
共通部分にはLabelやText等があるのですが、これは派生フォームからでも変更可能にしたいので、アクセシビリティをProtectedに変更しました。
これで派生フォームからも基本フォームの各コントロールにアクセス出来るようになったのですが、基本フォームと派生フォームで設定内容を統一させる方法が
分かりません。それぞれのフォームが参照する先は同じにしたいのですが、具体的には
どういった方法で実現すれば宜しいのでしょうか?
現在の状況は以下のコードのようになっており、基本フォームで変更した値は派生フォーム側でも反映されて表示されるのですが、派生フォームで変更した値を基本フォーム側で表示させる処理が分からなくて、つまずいている状態です。
根本的なところで間違っているかもしれませんが、宜しくお願い致します。

【呼び出し元】
private void cmdBase_Click(object sender, EventArgs e)
{
Kihon.Instance.Show();
}

private void cmdHasei_Click(object sender, EventArgs e)
{
Hasei hasei = new Hasei();
hasei.ShowDialog();
}

【基本フォーム】
// フォームのインスタンスを保持するフィールド
private static Kihon _instance;

public static Kihon Instance
{
get
{
// _instanceがnullまたは破棄されているときは、新しくインスタンスを作成する
if (_instance == null || _instance.IsDisposed)
_instance = new Kihon();
return _instance;
}
}

private string varValue;
public string TextValue
{
get
{
return varValue;
}
set
{
varValue = value;
}
}

//フォームを閉じずに隠すようにする
private void Kihon_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
this.Hide();

}

private void txtTest_TextChanged(object sender, EventArgs e)
{
TextValue = txtTest.Text;
}

【派生フォーム】
// コンストラクタ
public Hasei()
{
InitializeComponent();
txtTest.Text = Kihon.Instance.TextValue;

}
■No28449に返信(pooさんの記事)

共通部の処理をまとめる為に派生を使うのなら基本のクラスはインスタンス化
しないで派生クラスでインスタンス化するのが普通だと思います。

派生クラスの変更内容が基本クラスの値を変更するというのは派生関係を作っても起こりません。ましてやインスタンス化した後の話であればpublicメンバを使用した値の受け渡しが必要となります。これは派生は関係ありません。
shuさん、ありがとうございます。

> 共通部の処理をまとめる為に派生を使うのなら基本のクラスはインスタンス化
> しないで派生クラスでインスタンス化するのが普通だと思います。
確かに、まとめるだけの基本クラスならインスタンス化はしなくてもいいですね。
うっかりしておりました。

> 派生クラスの変更内容が基本クラスの値を変更するというのは派生関係を作って
> も起こりません。ましてやインスタンス化した後の話であればpublicメンバを
> 使用した値の受け渡しが必要となります。これは派生は関係ありません。

はい、その辺りの事は理解しておりましたが、質問させて頂いたような使い方をする事自体がそもそも間違っているのか?それとも
そういった使い方もありなのかというところで悩んでおりました。
やはり、現実的ではないのですかね。
2011/04/13(Wed) 15:35:14 編集(投稿者)

■No28456に返信(pooさんの記事)
> やはり、現実的ではないのですかね。
派生は関係ありません。明後日の方向を向いて質問しているだけだと
思われます。つまりは「理解してない」のだと思うのですが?

2つのインスタンス間でデータをやり取りしたいならすればいいだけ
のことです。派生は関係ありません。基本クラス2個のインスタンス
でもいいのでしょう?2つのインスタンス間での話をすれば良いのに
基本クラスだ派生クラスだと言っているのが関係ない話をしている
というだけに思います。
るしぇさん、ありがとうございます。
> 基本クラスだ派生クラスだと言っているのが関係ない話をしている
> というだけに思います。

最初に質問しました際に、以下のように記述しておりました。

> 複数フォームにて重複した共通部分があるため、以下サイトを参考に基本フォー> ムを作り、継承機能を活用しようと思っております。
>【参考サイト】
http://www.atmarkit.co.jp/fdotnet/dotnettips/324winbaseform/winbaseform.html

上記サイトを見て頂くと、基本フォーム・派生フォームと言っている内容が
お分かり頂けるかと思います。
るしぇさん、度々すみません。
先程、記述し忘れたので追記します。

データのやり取りについては、おっしゃるとおり、2つのインスタンス間で
データをやり取りすればいいだけの話ですね。
■No28475に返信(pooさんの記事)
> るしぇさん、ありがとうございます。
>>基本クラスだ派生クラスだと言っているのが関係ない話をしている
>>というだけに思います。
>
> 最初に質問しました際に、以下のように記述しておりました。
>
>>複数フォームにて重複した共通部分があるため、以下サイトを参考に基本フォー> ムを作り、継承機能を活用しようと思っております。
> >【参考サイト】
> http://www.atmarkit.co.jp/fdotnet/dotnettips/324winbaseform/winbaseform.html
>
> 上記サイトを見て頂くと、基本フォーム・派生フォームと言っている内容が
> お分かり頂けるかと思います。
最初から読んでいることを明示的に宣言した上で再度言います。
継承とは関係ありません。

継承はクラス設計の段階の話であり、構成要素、つまりはメンバの機能を
引き継ぐということです。データの引継ぎは全く話が別になります。
設計図の段階で「機能が共通している」と基本クラスを参照できるに
過ぎません。

現実のもので置き換えると、ある設計書を見ると「基本機能の設計は
既存の〜の設計書を参照」と書いてあるようなものです。これが継承です。

これに対して、具体的なデータは設計図をもとにした実物に格納されます。
テレビが1台あります。そのテレビに設計書上はビデオを付加した
だけのテレビデオが1台隣りにあったとします。テレビのチャンネル
を変えただけでテレビデオのチャンネルが変わることはありません。
インスタンスを生成した時点で別の個体だと認識します。

逆に、そんな動きをする方が現実離れしていてプログラマを混乱
させるので、まず、考えません。テレビとテレビデオが1台ずつ
ならそんな機能も便利に感じる人がいるかもしれませんが、実際は
何台も大量生産できるのですから、隣の家のチャンネルを変えたら
自分の家のチャンネルが変わるような機能は迷惑でしかありません。

実装するとしても、継承とは関係なく、1つのインスタンス内で
起こった(データ変更の)イベントをトリガーにして別のインス
タンスのデータを書き換える話になります。

継承を理由にデータの変更と結びつける事はできません。これは、
設計書の段階では、実物の製造番号を知ることができないという
話に似ています。VBの表現にすれば、インスタンスのメモリアド
レスが分からないため、命令しようが無いという事になります。
■No28449に返信(pooさんの記事)
> それぞれのフォームが参照する先は同じにしたいのですが、
> 具体的にはどういった方法で実現すれば宜しいのでしょうか?

端的に回答をさせて頂けば、"参照する先" を示すものをインスタンスとしての情報ではなく型として情報とすれば良いです。
C# で言えば静的メンバ (static) と呼ばれるものです。

後は上記の静的メンバにアクセスするための、静的なメソッドやプロパティを、
protected または protected internal 以上のスコープで実装すれば良いです。

この方法は実装している場所が基底クラスであり、スコープが protected であるため、継承と深く関係しているように見えますが、
その実、"参照する先" の実体がコントロールなど単独のインスタンス (ハンドル) を要するものであれば、あまり関係がないです。
関係がどうであれアクセス可能であれば実現できるからです (アクセス レベルくらいの関係しかない)。

# またこの方法は参照する先がインスタンス メンバであれば、ちょっと工夫が必要です。

> 派生フォームで変更した値を基本フォーム側で表示させる処理が分からなくて

どうしてもインスタンス メンバとして実装したいということであれば、
バインディングのような動作をするプロパティを相互に実装することになります。
また派生クラスは基底クラスから Factory に作成するなどして (他にも方法はありますが、いずれにしても) 基底クラス側でインスタンスを管理する必要が出てくるでしょう。
ちなみにこの方法は、継承とは 一 切 無 関 係 な方法です。

最後に、いずれの方法にしても一般的ではないと思います。

DOBON.NET | プログラミング道 | プログラミング掲示板