tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルクラスの記述法
記事No6245
投稿日: 2007/09/07(Fri) 10:45
投稿者ダンボ
クラスの記述法について質問です。
前提:AlbumDefクラスはBaseDefクラスを継承します。
下記2パターンの書き方ができます(並列記述とクラス内クラス)。

質問1.この2つの書き方の得失は何でしょうか?
質問2.継承先でMyBaseとMeの使い分けが分かりません。
    下記どちらでも良いみたいなんですが、得失は何でしょうか?
        AlbumDefクラスで再定義した場合だけ差が出るのですか?
            MyBase.Modified(innerLastAccess)
            Me.Modified(innerLastAccess)
質問3.Option Strict Onなのに、
    Public Overloads Function Modified(ByVal value As Boolean) As Boolean
    で、ワーニングもでない。Overloadsだからかな?


記述法1.並列記述
Option Strict On
Public MustInherit Class BaseDef
    Private innerModified As Boolean
    Public Overloads Function Modified() As Boolean
        Modified = innerModified
    End Function
    Public Overloads Function Modified(ByVal value As Boolean) As Boolean
        innerModified = value
    End Function
    Public Overloads Sub Modified(ByRef AccessDate As Date)
        innerModified = True
        AccessDate = Now
    End Function
End Class

Public Class AlbumDef
    Inherits BaseDef
    Private innerLastAccess As Date
    Public Sub Test()
        MyBase.Modified(innerLastAccess)
        Me.Modified(innerLastAccess)
    End Sub
End Class


記述法2.クラス内クラス
Option Strict On
Public MustInherit Class BaseDef
    Private innerModified As Boolean
    Public Overloads Function Modified() As Boolean
        Modified = innerModified
    End Function
    Public Overloads Function Modified(ByVal value As Boolean) As Boolean
        innerModified = value
    End Function
    Public Overloads Sub Modified(ByRef AccessDate As Date)
        innerModified = True
        AccessDate = Now
    End Function

    Public Class AlbumDef
        Inherits BaseDef
        Private innerLastAccess As Date
        Public Sub Test()
            MyBase.Modified(innerLastAccess)
            Me.Modified(innerLastAccess)
        End Sub
    End Class
End Class  

[ツリー表示へ]
タイトルRe: クラスの記述法
記事No6246
投稿日: 2007/09/07(Fri) 11:21
投稿者魔界の仮面弁士
> 質問1.この2つの書き方の得失は何でしょうか?
問題点として挙げられるのは、End Function/Sub の間違いによる BC30026 です。

動作面で見れば、どちらでも構いません。そのクラスを利用する側の立場で見たときに、
 '並列記述
 Dim X As New AlbumDef()
 'クラス内クラス
 Dim X As New BaseDef.AlbumDef()
のどちらが分かりやすいかで使い分ければよいでしょう。

個人的な意見としては、継承関係にあるものをクラス内クラスにする必要性は、
あまり感じられません。むしろ分かり難くなってしまうのではないでしょうか。

クラス内クラスは、どちらかといえば、親クラスに対して依存性の強いクラス、それも、
クラス外部で生成される事が少ないものに対して使うのが適しているように思います。

ちなみに、.NET Framework におけるクラス内クラスの実装例を見てみると、
System.Windows.Forms.TabControl 内の ControlCollection クラスや
System.Windows.Forms.Control 内の ControlCollection クラスなどがありますね。


> 質問2.継承先でMyBaseとMeの使い分けが分かりません。
>    下記どちらでも良いみたいなんですが、得失は何でしょうか?
MyBase は、継承元クラス上の実装を呼び出します。
MyClass は、継承先クラス上の実装を呼び出します。
Me は、インスタンス化されたクラス上の実装を呼び出します。

http://smdn.invisiblefulmoon.net/ikimasshoy/vbdotnet/memyclassmybase.html
http://blogs.wankuma.com/jeanne/archive/2006/11/09/44157.aspx


> 質問3.Option Strict Onなのに、
>     Public Overloads Function Modified(ByVal value As Boolean) As Boolean
>     で、ワーニングもでない。Overloadsだからかな?
どのような警告が出ることを期待しておられますか?

# 以下、どうでも良い話。
# 私はこういう時に、日本語の「警告」か、英語表記の「warning」を使うようにしています。
# カタカナで書くと、ウォーニングにすべきかワーニングにすべきかという話になるので。

[ツリー表示へ]
タイトルRe^2: クラスの記述法
記事No6247
投稿日: 2007/09/07(Fri) 11:39
投稿者ダンボ
魔界の仮面弁士 さん、いつもいつもありがとうございます。

> > 質問1.この2つの書き方の得失は何でしょうか?
> 問題点として挙げられるのは、End Function/Sub の間違いによる BC30026 です。

お言葉が理解できません(泣)。

> 動作面で見れば、どちらでも構いません。そのクラスを利用する側の立場で見たときに、
> クラス内クラスは、どちらかといえば、親クラスに対して依存性の強いクラス、それも、
> クラス外部で生成される事が少ないものに対して使うのが適しているように思います。

では、そのような判断基準で使い分けていきます。

> > 質問2.継承先でMyBaseとMeの使い分けが分かりません。
> MyBase は、継承元クラス上の実装を呼び出します。
> MyClass は、継承先クラス上の実装を呼び出します。
> Me は、インスタンス化されたクラス上の実装を呼び出します。

理解できました。Me は場合によってMyBaseかMyClassのどちらかになる(言い方変だけど)。


> > 質問3.Option Strict Onなのに、
> >     Public Overloads Function Modified(ByVal value As Boolean) As Boolean
> >     で、ワーニングもでない。Overloadsだからかな?
> どのような警告が出ることを期待しておられますか?

「Functionなのに値を返さない」という趣旨の警告です。
Overloadsをやめて単独にしても警告でませんねぇ。

[ツリー表示へ]
タイトルRe^3: クラスの記述法
記事No6248
投稿日: 2007/09/07(Fri) 12:07
投稿者魔界の仮面弁士
> > > 質問1.この2つの書き方の得失は何でしょうか?
> > 問題点として挙げられるのは、End Function/Sub の間違いによる BC30026 です。
> お言葉が理解できません(泣)。

BCxxxxx というのは、コンパイラ(VBC.EXE)が発するエラーコードです。
http://msdn2.microsoft.com/ja-jp/library/63wkx9xe%28vs.80%29.aspx

提示されたコードにある
> Public Overloads Sub Modified(ByRef AccessDate As Date)
>    :
> End Function
が、文法的に正しくないことはわかりますよね。


>>> 質問3.Option Strict Onなのに、
>>>     Public Overloads Function Modified(ByVal value As Boolean) As Boolean
>>>     で、ワーニングもでない。Overloadsだからかな?
>> どのような警告が出ることを期待しておられますか?
> 「Functionなのに値を返さない」という趣旨の警告です。

あぁ、BC42105 の警告ですか。それは、Boolean が値型だからです。
http://msdn2.microsoft.com/ja-jp/library/87x5f80y%28vs.80%29.aspx

[ツリー表示へ]
タイトル[解決] クラスの記述法
記事No6250
投稿日: 2007/09/07(Fri) 12:56
投稿者ダンボ
> > Public Overloads Sub Modified(ByRef AccessDate As Date)
> > End Function

失礼しました。End Subの誤記です。
FunctionとSub がOverloads できるんだって意外ですね。

> あぁ、BC42105 の警告ですか。それは、Boolean が値型だからです。

了解しました。
警告した方がいいんではないかなぁ>MS
Option Strict On なんだから。

[ツリー表示へ]
タイトルRe: [解決] クラスの記述法
記事No6251
投稿日: 2007/09/07(Fri) 13:26
投稿者魔界の仮面弁士
> FunctionとSub がOverloads できるんだって意外ですね。
IL 的には、戻り値の型が void 型か bool 型かの違いしか無いですしね。

ちなみに .NET そのものは、「引数が同一で戻り値の型のみが異なるオーバーロード」
さえもサポートしています。C# や VB では実装/利用できませんけれどね。


> 警告した方がいいんではないかなぁ>MS
> Option Strict On なんだから。
『曖昧な型』の問題ではないので、Option Strict に含めるのは個人的には違和感…。(^^;



>>>>> 質問2.継承先でMyBaseとMeの使い分けが分かりません。
少なくとも、
  Public Overrides Function Method1() As String
    Return "[" & MyBase.Method1() & "]"
  End Function
のような処理で、この MyBase を Me や MyClass にできないという事はわかりますよね。

>>> 理解できました。Me は場合によってMyBaseかMyClassのどちらかになる(言い方変だけど)。

"言い方変だけど" という事ですので、表現の曖昧さによるものかも知れませんが、
そのような理解の仕方には、幾許かの誤解を含んでいそうな気がします。
「MyBaseになる場合」と「MyClassになる場合」の具体例を出してみてもらえますか?


たまたま、MyBase や MyClass と同じ結果を返す場合もあるというだけであって、
別に、Me が MyBase や MyClass に変化するというわけではありませんよ。


たとえば、下記のサンプルにおいて『 MsgBox(New Poodle().Test()) 』を実行すると、
+--------------------------
|      Me:プードルクラス
|  MyBase:動物クラス
| MyClass:犬クラス
+--------------------------
という結果となり、それぞれが別の意味を持っていることを確認できます。


'===================
Public Class Animal
    Public Overrides Function ToString() As String
        Return "動物クラス"
    End Function
End Class

Public Class Dog
    Inherits Animal
    Public Overrides Function ToString() As String
        Return "犬クラス"
    End Function
    Public Function Test() As String
        With New System.Text.StringBuilder()
            .AppendLine("     Me:" &      Me.ToString())
            .AppendLine(" MyBase:" &  MyBase.ToString())
            .AppendLine("MyClass:" & MyClass.ToString())
            Return .ToString()
        End With
    End Function
End Class

Public Class Poodle
    Inherits Dog
    Public Overrides Function ToString() As String
        Return "プードルクラス"
    End Function
End Class

[ツリー表示へ]
タイトルRe^2: [解決] クラスの記述法
記事No6252
投稿日: 2007/09/07(Fri) 14:30
投稿者ダンボ
> >>> 理解できました。Me は場合によってMyBaseかMyClassのどちらかになる(言い方変だけど)。
>
> "言い方変だけど" という事ですので、表現の曖昧さによるものかも知れませんが、
> そのような理解の仕方には、幾許かの誤解を含んでいそうな気がします。
> 「MyBaseになる場合」と「MyClassになる場合」の具体例を出してみてもらえますか?
>

こんな検証用プログラムを作りました。
そのまま実行すれば、
MyCLASS
MyBase
MyCLASS
でしたので「MeはMyClassになった」。

AlbumDefの方のModifiedメソッドをコメントアウトして実行すると
MyBase   <----(これは納得行かないけど。だってMyClassでは定義していないもの)
MyBase
MyBase
でしたので「MeはMyBaseになった」。

どうも表現が悪くてすみません。
「実行されるロジックはMyClassのもの/MyBaseのもの」ならまだ増しかも。



Option Strict On
Module Module1
    Public MustInherit Class BaseDef
        Public Sub Modified()
            Console.WriteLine("MyBase")
        End Sub
    End Class
    Public Class AlbumDef
        Inherits BaseDef
        Public Overloads Sub Modified()
            Console.WriteLine("MyCLASS")
        End Sub
        Public Sub Test()
            MyClass.Modified()
            MyBase.Modified()
            Me.Modified()
        End Sub
    End Class

    Public Sub main()
        Dim Album As New AlbumDef
        Album.Test()
        Console.Read()
    End Sub
End Module

[ツリー表示へ]
タイトルRe^3: [解決] クラスの記述法
記事No6258
投稿日: 2007/09/07(Fri) 16:16
投稿者魔界の仮面弁士
No.6251 の例で言えば、

(1) MsgBox(New Poodle().Test())
+--------------------------
|      Me:プードルクラス
|  MyBase:動物クラス
| MyClass:犬クラス
+--------------------------


(2) MsgBox(New Dog().Test())
+--------------------------
|      Me:犬クラス
|  MyBase:動物クラス
| MyClass:犬クラス
+--------------------------

となりますが、(2) で Me と MyClass が同じ結果を返すからといって、
Me が MyClass として扱われたというわけではありません。


Me.ToString() の動作は、
  New されたインスタンスが Dog だったら、「犬クラス」
  New されたインスタンスが Poodle なら、「プードルクラス」
となるだけです。

一方、MyClass.ToString() の動作は、いずれも
  Test メソッドは Dog クラスにだけ実装されているので、「犬クラス」
を返すことになります。


===========================================================================

> こんな検証用プログラムを作りました。
> Dim Album As New AlbumDef
> Album.Test()

「Dim Album As New AlbumDef」とはすなわち、
「Dim Album As AlbumDef = New AlbumDef()」の省略表記ですよね。

まずは、
 インスタンス(New で生成されたオブジェクトのこと)の型は、AlbumDef 型である。
 Album 変数の型もまた、AlbumDef 型である。
 Album.Test() によって、「AlubumDef クラスに実装されている Test メソッド」が実行される。
という 3 つの点を抑えておいてください。


> そのまま実行すれば、
> MyCLASS
> MyBase
> MyCLASS
> でしたので「MeはMyClassになった」。

AlubumDef の Test メソッド内で行われている事を追跡してみましょう。


> MyClass.Modified()
 → このクラス(AlbumDef クラス)に実装されている Modified メソッドを実行せよ。
 →→ "MyCLASS" が出力される。

> MyBase.Modified()
 → 継承元クラス(BaseDef クラス)に実装されている Modified メソッドを実行せよ。
 →→ "MyBase" が出力される。

> Me.Modified()
 → 現在のインスタンスに実装されている Modified メソッドを実行せよ。
 →→ Album 変数に代入されているインスタンスは、AlbumDef 型。
 →→→ "MyBase" が出力される。


===========================================================================

> AlbumDefの方のModifiedメソッドをコメントアウトして実行すると
> MyBase   <----(これは納得行かないけど。だってMyClassでは定義していないもの)
> MyBase
> MyBase
> でしたので「MeはMyBaseになった」。

この場合、AlbumDef では Modified メソッドが再定義(シャドウ または オーバーライド)されて
いないため、結果的に BaseDef の Modified メソッドが呼び出されることになります。

# 面倒なので、[シャドウとオーバーライドの違い] は、ここでは触れません。下記参照。
# http://msdn2.microsoft.com/ja-jp/library/ms172785%28VS.80%29.aspx


> MyClass.Modified()
 → このクラス(AlbumDef クラス)に実装されている Modified メソッドを実行せよ。
 →→ AlbumDef では Modified が再定義されていない。BaseDef.Modified が実行される。
 →→→ "MyBase" が出力される。

> MyBase.Modified()
 → 継承元クラス(BaseDef クラス)に実装されている Modified メソッドを実行せよ。
 →→ "MyBase" が出力される。

> Me.Modified()
 → 現在のインスタンスに実装されている Modified メソッドを実行せよ。
 →→ Album 変数に代入されているインスタンスは、AlbumDef 型。
 →→→ AlbumDef では Modified が再定義されていない。BaseDef.Modified が実行される。
 →→→→ "MyBase" が出力される。

[ツリー表示へ]