- PR -

C# 特定のプロパティへの外部からのアクセスを隠蔽したい

投稿者投稿内容
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2004-12-06 22:55
暗黙のキャストに全く気がつきませんでした。
継承では、この方法が限界ということですね。
本当にありがとうございます。

[quote]
Jittaさんの書き込み (2004-12-06 22:29) より:
[quote]
ひろしさんの書き込み (2004-12-06 21:56) より:

なぜYellowTextBoxの背景がピンク色に書き換えることができるか分かりません。
わたしはどこをどう勘違いしているのでしょうか?
[/quote]
 つまり、私がやったことと一緒ですね。なちゃさんやmeiさんが書かれているとおりで、継承によってpublicで公開されたメソッドを隠蔽、見えなくすることはできません。ん〜っと、publicで宣言されたメソッドを、private、publicで宣言し直すことはできません。暗黙的に、継承元のクラスにキャストされます。私は元々C++なので、C++的には「おかしい」のですが、C#やVB.NETでは仕様のようです。

 したがって、
this.textBox1.BackColor = System.Drawing.Color.Pink;
このコードは、
((System.Windows.Forms.TextBox)this.textBox1).BackColor = Color.Pink;
として解釈され、またILにもそう訳されます。第一、このコードがコンパイルエラーにならないのがおかしいと思いませんか?

 ユーザ入力を受け付けなくするには、public overrideで継承して、setアクセスメソッド内で握りつぶすしかないようです。
[code]
class YellowTextBox : TextBox {
public [i]override[/i] BackColor {
get {
return base.BackColor;
}
set { // 黄色にしかならない
base.BackColor = Color.Yellow;
}
}
}
[/code]
[code]
class YellowTextBox : TextBox {
public [i]new[/i] BackColor {
get {
return base.BackColor;
}
set { // 上位クラスにキャストすれば、黄色以外も可能
base.BackColor = Color.Yellow;
}
}
}
[/code]

[/quote]
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2004-12-06 23:07
ご回答ありがとうございます。
わたしがしたかったことはmeiさんが書かれている通りの処理です。
そして、ひたすらひもづける苦労を回避するためにリフレクションを活用することを
考えていました。
継承にせよ、Classの再構築にせよ、C#では、エレガントな記述方法が不可能ですね。
C#の機能に期待していただけに、残念な結果でした。
ReflectionやRealProxyには興味がありますので、
機会があればまた質問すると思います。その時は宜しくお願いします。


[quote]
meiさんの書き込み (2004-12-06 21:50) より:
こんばんは、meiです。

[quote]
ひろしさんの書き込み (2004-12-06 19:37) より:
private tempを作成するところまではわかりますが、tempが持つ特徴から必要な
ものだけをPinkTextBoxに引き継がせるエレガントな方法が分かりません。
例えば下記のようにしてひたすら全てのメンバー(BackColor以外)をひもづけるしか
無いという理解で正しいしょうか?
[/quote]

ええ、tempへの委譲処理を書くことになります。
TextBoxのプロパティが多いですが、作っているアプリケーションですべてのプロパティを必要とする訳ではないので、実際はそれほど多くないと思います。

あと、質問なのですが、ここで言っている隠蔽とは、
[code]
MyTextBox tb = new MyTextBox();
tb.Text = "ABC";
[/code]
このようなコードをコンパイルエラーにすることでしょうか?
もし、これが狙いでしたら継承は使えません。

そうではなく、単に親クラス(TextBox)のプロパティを書き換えられたくないのでしたら、overrideして、set {...}の処理をつぶして、クラス内部からはbase.Textのように親クラスのプロパティを呼べは良いです。そのほかだと、xxxChangedイベントで強引に値を戻してやることも出来ます。(お勧めしませんけど・・・)

どうしてもコンパイル時に隠蔽したいのなら、ラッパークラスを作ってひたすら委譲するしかありません。力技が好ましくない場合は、リフレクションを使って雛形を自動生成させたり、RealProxy/ContextBoundを使ってメソッド呼び出しに割り込むといった手も取れますが、実現したい内容に比べて処理が難しくになるのでお勧めしません。

http://www.ne.jp/asahi/nami/mei/cstips/adapter.html
↑昔遊びで作ったRealProxyのサンプルです。参考までにどうぞ。


[ メッセージ編集済み 編集者: mei 編集日時 2004-12-06 21:54 ]

[ メッセージ編集済み 編集者: mei 編集日時 2004-12-06 22:01 ]
[/quote]

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