tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトル基底関数の振る舞い
記事No4852
投稿日: 2007/01/19(Fri) 10:39
投稿者DOON
DOONです。
お世話になっています。

下の質問でもお世話になりました。
現在vb.net 2005 windowsxpでユーザーコントロールを作成中です。
そこで、基底関数の振る舞いについて分からなくなりました。
ご存知の方、教えてください。
少し文章が長くなりますが、ご了承ください。

今作成している、ユーザーコントロールはTextBoxのみの作成です。
TextBoxをそのまま継承して作成しています。
ここで例として、TextChangedのイベントの中身を実装したユーザーコントロールを
作成しようとしています。
ユーザーコントロールのソース内に、
OnTextChangedを書いてみました。以下になります。
    Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)

        MyBase.OnTextChanged(e)
    End Sub
すると自動でMyBase.OnTextChanged(e)が書き込まれました。
そのあと、テスト用に、同じソリューションファイル内に
WindowsApplicationプロジェクトを作成。
フォームにそのユーザーコントロールを貼り付けました。
貼り付けたテキストボックスをTextBox1とします。
そのWindowsApplicationのフォームのソースに
    Private Sub TextBox1_TextChanged(ByVal .....

    End Sub
と書き込みました。
実際WindowsApplicationを実行してみました。
textbox1に値を代入すると、
ユーザーコントロール内のOnTextChangedが走ります。
そして、基底関数を呼びます。
その後にWindowsApplicationのTextBox1_TextChangedが走ります。

この振る舞いが正しいとは思うので、それを踏まえてユーザーコントロールを
作成しようと思いました。そもそもWindowsApplication内にTextBox1_TextChanged
という、ソースは書かないようにはするつもりです。

質問はこのMyBase.OnTextChanged(e)はユーザーコントロールの
基底関数のメソッドを呼ぶのではないのですか?
私の中ではユーザーコントロールの基底関数はSystem.windows.formだと思うのですが?
大きな勘違いがありそうです。

どなたか教えていただけませんでしょうか?

[ツリー表示へ]
タイトルRe: 基底関数の振る舞い
記事No4857
投稿日: 2007/01/19(Fri) 12:19
投稿者Hongliang
> 質問はこのMyBase.OnTextChanged(e)はユーザーコントロールの
> 基底関数のメソッドを呼ぶのではないのですか?
> 私の中ではユーザーコントロールの基底関数はSystem.windows.formだと思うのですが?
> 大きな勘違いがありそうです。

基底クラスのメソッドを呼び出します。TextBox クラスを継承しているのですから、TextBox.OnTex
tChanged を呼び出します。
TextBox クラスは、リファレンスを辿ると分かりますが
Object
MarshalByRefObject
Component
Control
TextBoxBase
TextBox
という順に派生しています。この次に作成なさっているユーザコントロールが来るわけですが。
基底と言うのはこのツリーを上に遡る方向で、派生(継承)は下に下りる方向です。
この継承ツリーのどこかで初めて OnTextChanged が定義され、以降のクラスはそれをそのまま使っ
たりオーバーライドしたりするわけです。
当然、Form クラスなんてまったく関係ありません。

では何故 Form に TextBox1_TextChanged みたいなメソッドを書くと呼び出されるのかと言うと、
イベントという仕組み(Handles キーワードがポイント)を使って、OnTextChanged メソッドの内部
で TextBox1_TextChanged を呼び出しているからです。
もうちょっと詳しく言うと、Form は TextBox に「OnTextChanged が呼び出されたら TextBox1_Tex
tChanged を呼んでくれ」と事前に言っているわけです(この「OnTextChanged が呼び出されたら」が
TextChanged イベントです)。

オーバーライドした場合、派生クラスが基底クラスの同名メソッドを呼び出すかどうかは任意です

もし TextBox クラスから派生させたクラスで OnTextChanged をオーバーライドし、そこで MyBase
.OnTextChanged、つまり TextBox の OnTextChanged を呼び出さなかった場合、TextBox の OnTextC
hanged が実行されないため、当然ながら Form が事前に言っていた「TextBox1_TextChanged を呼ん
でくれ」は意味を持たなくなります。

[ツリー表示へ]
タイトルRe^2: 基底関数の振る舞い
記事No4858
投稿日: 2007/01/19(Fri) 13:09
投稿者DOON
DOONです。早速の返事ありがとうございます。
こないだの質問にひきつづきありがとうございます。
分かりやすくて、理解できたと思います。

> 当然、Form クラスなんてまったく関係ありません。
すいません、まったくの検討ちがいですね。

> では何故 Form に TextBox1_TextChanged みたいなメソッドを書くと呼び出されるのかと言うと、
> イベントという仕組み(Handles キーワードがポイント)を使って、
このHandlesのソースは見れないんですかね。
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
このイベント設定ですべてをまかなっているとかですかね。

> Form は TextBox に「OnTextChanged が呼び出されたら
> TextBox1_TextChanged を呼んでくれ
MyBase.OnTextChangedで呼ばれていく先にFormと紐付けられる予定の関数が
潜んでいるということであってますでしょうか?

理解できてますでしょうか?
この答えを聞いて、考えをまとめると、やはりUserControl内では
OnTextChanged等のOnの付く関数をオーバーライドして修正します。
さらに基底関数は呼ばないようにします。このコントロールを使われた先で
何かやられると困りそうなので。

UserControl内でもTextBox1_TextChangedと書くこともできるのに
なぜOnTextChangedも書くことができるのか不思議でした。

ありがとうございました。

[ツリー表示へ]
タイトルRe^3: 基底関数の振る舞い
記事No4863
投稿日: 2007/01/19(Fri) 17:46
投稿者Hongliang
> > イベントという仕組み(Handles キーワードがポイント)を使って、
> このHandlesのソースは見れないんですかね。
> Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
> このイベント設定ですべてをまかなっているとかですかね。

ソースと言うか、キーワード(予約語)ですから。
確かにコンパイラ内部では AddHandler とかに展開されますけど。

> MyBase.OnTextChangedで呼ばれていく先にFormと紐付けられる予定の関数が
> 潜んでいるということであってますでしょうか?

なんか違う……。
TextBox の TextChanged に、Form は呼び出してほしいメソッドを登録する。
TextBox かその基底クラスの OnTextChanged が TextChanged に登録されたメソッドを呼び出す。

> この答えを聞いて、考えをまとめると、やはりUserControl内では
> OnTextChanged等のOnの付く関数をオーバーライドして修正します。
> さらに基底関数は呼ばないようにします。このコントロールを使われた先で
> 何かやられると困りそうなので。

いやいやいや、OnHogehoge は呼び出してあげてください。リファレンスにも基底クラスのを呼び出
せと書いてあります。
使用者は文字列が変更されたときに何かしたいから TextChanged を利用するのに、それが使えない
のでは二進も三進も行きません。
何かやって困るのはその利用者だけですが、そもそもできないのでは何かやっても困らない利用者
全員に影響がでます。

[ツリー表示へ]
タイトルRe^4: 基底関数の振る舞い
記事No4864
投稿日: 2007/01/19(Fri) 18:09
投稿者DOON
DOONです。
本当に返事ありがとうございます。


> ソースと言うか、キーワード(予約語)ですから。
> 確かにコンパイラ内部では AddHandler とかに展開されますけど。

これは、Handlesがどこかにソースに書いてあるのかな、みてみたいな
とおもって、さがしたらFriend WithEventsとあったので
これかなと思って、書きました。

> なんか違う……。
> TextBox の TextChanged に、Form は呼び出してほしいメソッドを登録する。
> TextBox かその基底クラスの OnTextChanged が TextChanged に登録されたメソッドを呼び出す。
>
理解しました。いや、本当は半分ぐらいしか分かってないですけど。
もっと勉強します。

>
> いやいやいや、OnHogehoge は呼び出してあげてください。
無知の極みですね。
OnHogehogeは残すようにします。


本当にありがとうございます

[ツリー表示へ]