none
プロパティのGetメソッドについて RRS feed

  • 質問

  • おはようございます。

    VB2005+SQLServerExpressで開発をしています。

    基本的な質問で申し訳ないのですが、クラス内にプロパティを用意する際、GetメソッドとSetメソッドをセットすると思います。

    Setメソッドに関しては、DBへの登録前のデータチェックなどに利用をしているのですが、Getメソッドはどのような場合に
    活用をするのでしょうか。

    クラスの活用方法などがいまだ、よくわかっていないので、どうしても、今でも使用しているAccessのイメージが抜けず、
    データをフォームに表示する際は、以下のように記述をしてしまいます。

      Private Sub Disp_PtData(ByVal PtCodeValue As String)

            Dim PtTable As New clsPtTableIO
            Dim PtDT As New DataTable
            Dim TimeStampValue(8) As Byte
            Dim AddressTable As New clsPTAddressTableIO
            Dim AddressDT As New DataTable
            Dim NyuuinTable As New clsNyuuinTableIO
            Dim NyuuinDT As DataTable

            Try
                'PtDT = PtTable.GetSelectData(Frm.lst_Ichiran.SelectedItems.Item(0).Text)
                PtDT = PtTable.GetKeyData(PtCodeValue)
                AddressDT = AddressTable.GetKeyData(PtCodeValue, 0)
                NyuuinDT = NyuuinTable.GetKeyData(PtCodeValue)

                'MessageBox.Show(CStr(AddressDT.Rows(0)("adr_id")))

                'レコードがあった場合
                If PtDT.Rows.Count = 1 Then
                    With Me
                        .txt_PtCode.Text = CStr(F_NZ(PtDT.Rows(0)("pt_ptcode"), ""))
                        .txt_PtName.Text = CStr(F_NZ(PtDT.Rows(0)("pt_name"), ""))
                        .txt_PtKana.Text = CStr(F_NZ(PtDT.Rows(0)("pt_kana"), ""))
                        .txt_Sex.Text = CStr(F_NZ(PtDT.Rows(0)("pt_sex"), ""))

                        '性別のラジオボタンの選択
                        If .txt_Sex.Text = "1" Then
                            .rdb_Man.Checked = True
                        ElseIf .txt_Sex.Text = "2" Then
                            .rdb_Woman.Checked = True
                        End If

                        .txt_Birthday.Text = Change_Wareki(CStr(F_NZ(PtDT.Rows(0)("pt_birthday"), "")))
                        .txt_Tel.Text = CStr(F_NZ(PtDT.Rows(0)("pt_tel"), ""))
                        .txt_Keitai.Text = CStr(F_NZ(PtDT.Rows(0)("pt_keitai"), ""))

                        PtTimeStampValue = CType(PtDT.Rows(0)("pt_ts"), Byte())

                    End With


    (コードの一部抜粋です。)
    DBから取得したデータをそのままフォームの各コントロールへセットしています。

    となると、プロパティで指定をするGetメソッドはどのような際に使うのかが疑問です。

    しかし、根本的に自分のコードの書き方がおかしいのでは、とも思ってもいるので質問をさせていただきました。
    (現状は問題なく動いてはいます。)

    どうか、アドバイスお願いします。

    2009年5月17日 22:44

回答

  • データのエラーチェックが1箇所で行うことができるので、便利になったのですが、それ以外に何かメリットは
    あるのでしょうか。

    これは戻り値にクラスを使った場合ということですよね?
    一般的なオブジェクト指向っぽい話になってしまいますが、例えば戻り値をクラスではなく構造体にした場合と比較してみましょう。
    構造体は値型であり、クラスは参照型です。私の好きなメタファを用いてみます。
    ここに2つのテキストファイルがあります。中身は、コード、氏名、名前カナ、性別が書かれており、この2つのテキストファイルは全く同じです。
    しかし、片方はショーカットが作れますが、片方は作れません。前者がクラスであり、後者が構造体になります。
    ショートカットを作成できれば、いろんなフォルダにショートカットを作成できます。実体は一つですから、どのショートカットからそのテキストファイルを開いて更新しても同じです。
    一方、ショートカットが作成できないテキストファイルはこのようなことができません。いろんなフォルダにはそのテキストファイルのコピーを作成して置く必要があります。それぞれは独立していますから、あるフォルダからそのテキストファイルを開いて変更しても、他には影響を与えません。しかし、ショートカット経由ではないので、そのテキストファイルに速くアクセスすることができます。
    #インスタンス経由でアクセスするというのは、必ずショートカット経由でアクセスするということです。クラスの場合はインスタンスを作成することが多いので、多くはショートカット経由でアクセスしていることになります。

    C#ですが基本は同じですので、以下が参考になると思います。

    値型と参照型
    http://ufcpp.net/study/csharp/oo_reference.html
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年5月18日 5:09
    モデレータ

すべての返信

  • 必ずしもGetアクセッサメソッドを定義しなくてもよいというのはご存じですよね?

    さて、

    PtDT = PtTable.GetKeyData(PtCodeValue)

    の部分ですが、戻り値を一般的なDataTable型ではなく、独自に定義されたクラスにされてみてはいかがでしょうか? 例えばそのクラスをPersonとすれば、以下のように書けます。

    Dim p as Person
    p = PtTable.GetKeyData(PtCodeValue)

    if p IsNot Nothing Then
    With Me
           .txt_PtCode.Text = p.Ptcode
           .txt_PtName.Text = p.Ptname
           .txt_PtKana.Text = p.Kana
           .txt_Sex.Text = p.Sex
              .
              .
              .

    Ptcode, Ptname, Kana, SexはPersonクラスのプロパティですので、Getアクセッサメソッドを定義しています。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年5月18日 0:55
    モデレータ
  • ご回答ありがとうございます。

    Getアクセッサメソッドを定義しなくても良い場合があるとは知りませんでした。
    (コーディング中に定義して下さいというようなメッセージがでるので、絶対に定義しなければならないと思っていました。)

    戻り値にクラスを使うことができることも知りませんでした。

    もともと、今回のコードで取得していた基本情報は他でも使用する用途があったので、プロパティのみを独立のクラスと
    しておりましたので、それを使ってみたところ、同じように表示ができました。

    データのエラーチェックが1箇所で行うことができるので、便利になったのですが、それ以外に何かメリットは
    あるのでしょうか。
    2009年5月18日 4:22
  • データのエラーチェックが1箇所で行うことができるので、便利になったのですが、それ以外に何かメリットは
    あるのでしょうか。

    これは戻り値にクラスを使った場合ということですよね?
    一般的なオブジェクト指向っぽい話になってしまいますが、例えば戻り値をクラスではなく構造体にした場合と比較してみましょう。
    構造体は値型であり、クラスは参照型です。私の好きなメタファを用いてみます。
    ここに2つのテキストファイルがあります。中身は、コード、氏名、名前カナ、性別が書かれており、この2つのテキストファイルは全く同じです。
    しかし、片方はショーカットが作れますが、片方は作れません。前者がクラスであり、後者が構造体になります。
    ショートカットを作成できれば、いろんなフォルダにショートカットを作成できます。実体は一つですから、どのショートカットからそのテキストファイルを開いて更新しても同じです。
    一方、ショートカットが作成できないテキストファイルはこのようなことができません。いろんなフォルダにはそのテキストファイルのコピーを作成して置く必要があります。それぞれは独立していますから、あるフォルダからそのテキストファイルを開いて変更しても、他には影響を与えません。しかし、ショートカット経由ではないので、そのテキストファイルに速くアクセスすることができます。
    #インスタンス経由でアクセスするというのは、必ずショートカット経由でアクセスするということです。クラスの場合はインスタンスを作成することが多いので、多くはショートカット経由でアクセスしていることになります。

    C#ですが基本は同じですので、以下が参考になると思います。

    値型と参照型
    http://ufcpp.net/study/csharp/oo_reference.html
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年5月18日 5:09
    モデレータ
  • ご回答ありがとうございます。

    ちょっと、今の私には難しい内容のようです。
    頑張って勉強していきたいと思います。

    今までは、より早く処理ができること と思っていろいろと調べていましたが、私がやろうとしていることなど
    たいした処理時間がかかるようなものではないので、わかりやすく、ミスが減るようなコーディングを
    勉強していきたいと思います。

    最後になるのですが、もう1点だけお願いします。
    ケースバイケースとは思うのですが、今回のようなDBアプリケーションの場合、データの追加、表示に
    使用するプロパティなどはクラスとして独立させたほうが良いのでしょうか。

    いろいろと調べていると、時々このようなコーディングを見かけるので、何か意味があるのかなとは
    思ってはいたのですが、わからずじまいです。

    もっと、勉強したいと思います。

    2009年5月18日 7:53
  • 用途によりますが、型付DataSetや素のDataSetや自前のクラスなんかを使い分けると思います。
    DataBindingとかを使う場合ですが、以下のBlogにDataTableとかをそのまま使う時と、自分で作ったクラスを使うときの指針的なものが書いてあったと思います。
    http://blogs.msdn.com/nakama/archive/2009/02/26/9446324.aspx

    確か、ちょっと凝ったことやるなら自前のクラスを使うといった感じだったと記憶しています。


    かずき Blog:http://blogs.wankuma.com/kazuki/
    2009年5月18日 13:17
  • > Setメソッドに関しては、DBへの登録前のデータチェックなどに利用をしているので
    > すが、Getメソッドはどのような場合に活用をするのでしょうか。

    一般的な話として、プロパティを使う理由や基本的な使い方はご存知でしょうか? もし
    答えが No なら、C# での例ですが、一度以下のサイトを読んではいかがでしょうか。

    プロパティ
    http://ufcpp.net/study/csharp/oo_property.html

    プロパティの使用 (C# プログラミング ガイド)
    http://msdn.microsoft.com/ja-jp/library/w86s7x04.aspx

    型付 DataSet + TableAdapter(xsd ファイル)を作って(ウィザードベースでコードが
    自動生成されます)、その中でプロパティがどのように使われているか見てはいかがで
    すか?

    2009年5月18日 14:02
  • ケースバイケースとは思うのですが、今回のようなDBアプリケーションの場合、データの追加、表示に
    使用するプロパティなどはクラスとして独立させたほうが良いのでしょうか。

    なぜクラスを定義するのでしょう? それはクラスという固まり(オブジェクト)で整理整頓できるからです。言い方を変えれば、クラスとはコードの整理整頓の方法だとも言えます。例えば、DVDを見るとしましょう。DVDプレイヤーにDVDを入れて、それをテレビで見ることになります。ここでDVDとDVDプレヤーとテレビという3つのオブジェクトが出てきました。現実の世界はこのようにオブジェクトが関係し合って、一つの目的(この場合はDVDは見る)を達成しています。もし、このようなオブジェクトに分かれていなければ、DVD+DVDプレヤー+テレビ一体型の一つの装置になります。これでもDVDは見れますが、将来その装置でブルーレイが見たくなった時は困ってしまいます。
    オブジェクト指向とはこのような一つの装置をオブジェクトにばらしていくことです。オブジェクトとはよく言われるように属性と機能を持っているものです。例えばDVDプレヤーの場合、属性が本体の色、入力端子数、動作電圧など、機能が再生、早送り、倍速再生などになります。
    この属性と機能という考え方は、プログラムの世界でもよく当てはまります。属性は値で、機能は関数になります。そこでプログラムの世界でもオブジェクトとしてばらすとうまく整理できるようになり、このオブジェクトをクラスと呼ぶのです。

    DVDをデータソース、DVDプレヤーをデータアクセスクラス、テレビをフォームと考えることができます。
    もしDVDプレヤーがなければ、何やらテレビの付いた装置にDVDを挿入することになるでしょう。
    オブジェクトに分解されていれば、例えばブルーレイが見たくなった場合、DVD+ブルーレイのプレイヤーに取り替えるだけで済みます。
    さて、DVDで吹き替え音声に切り替えようとしました。実際にはそのDVDに吹き替え音声はないのでエラーになります。このエラーチェックはどこで行うのが適切でしょうか? 言うまでもなくDVDプレイヤーでしょう。もし、テレビでエラーチェックをしていれば、DVDプレイヤーと通信しなければできませんし、DVDプレイヤーが変わったら通信できなくなるかもしれません。一番問題なのは特定のDVDプレイヤーに依存しているということです。それぞれのオブジェクトは他のオブジェクトから完全に独立しているのが理想です。なぜなら、そのオブジェクトをいじっても、他に影響を与えないからです。テレビは入力信号というインターフェースだけ用意しておいて、入力信号を映し出すという機能さえあれば、他から完全に独立します。

    以上のようにオブジェクトに適切にばらされていれば、修正や発展が比較的楽にできることがわかります。結局のところ、オブジェクトによって適切に分割されたプログラム、つまりクラスによって整理整頓されたプログラムは、後で楽ができるのです。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年5月18日 15:58
    モデレータ
  • プロパティについて、わからないことがありますので、大変申し訳ありませんが、再びお願いします。

    以下のプロパティがあるとします。

    'ID
        Public Property ID() As Integer
            Get
                ID = IDValue
            End Get

            Set(ByVal value As Integer)
                If IsDBNull(CObj(value)) Or CStr(value) = "" Then
                    IDValue = 0
                Else
                    IDValue = value
                End If
            End Set
        End Property

    フォーム上のテキストボックスの値を取得するとします。

    テキストボックスが空白「””」の場合は、「0」をプロパティにセットしたいので、上記のように記述をしてみたのですが、

    クラス名.ID = Cint(Me.txt_MrrID.Text)

    としないと、値のセットができません。

    基本がわかっていなくて、大変申し訳ないのですが、プロパティをObject型として宣言をして、必要な型に
    変換をするのか、フォームの値などを取得する際に、フォームで値を判定してから、プロパティに値を
    セットするのか、どちらになるのでしょうか。

    どうか、よろしくお願いします。

    2009年5月24日 8:50
  • ID プロパティは Integer 型として定義しているので、値を設定する時にも Integer の値を代入するしかありません。
    よって、

    クラス名.ID = Cint(Me.txt_MrrID.Text)

    でしか値のセットができないのは仕方がありません。

    プロパティの型と異なる型で値をセットしたいのであれば、別のプロパティなりメソッドなりを定義するのが自然に思えます。

    Public Sub SetIDByObject(ByVal obj As Object)
        If obj Is Nothing Or obj.ToString().Length = 0 Then
            IDValue = 0
        Else
            IDValue = CInt(obj)
        End If
    End Sub
    といった具合でしょうか。Object 型でなくても String 型でも構わないように思いますが。

    ところで、テキスト ボックスの値が Integer になり得ない値(例えば "ABC" とか)の考慮は必要ないですか?

    2009年5月24日 9:47
  • テキストボックスが空白「””」の場合は、「0」をプロパティにセットしたいので、上記のように記述をしてみたのですが、

    クラス名.ID = Cint(Me.txt_MrrID.Text)

    としないと、値のセットができません。

    基本がわかっていなくて、大変申し訳ないのですが、プロパティをObject型として宣言をして、必要な型に
    変換をするのか、フォームの値などを取得する際に、フォームで値を判定してから、プロパティに値を
    セットするのか、どちらになるのでしょうか。

    たとえば Form の Width プロパティは Integer で定義されていて、文字列を元に Width を変更しようとしたら、変更する側が CInt しますよね。
    入れる側の都合より、そのプロパティがどういう意味を持つか、どの型が一番自然かを考えてプロパティの型を決定するようにしましょう。

    で、「空白の場合に 0 をセットしたい」のなら、
    • まず空白かどうかを調べて、空白なら 0 を代入する。
    • そうでないなら、CInt など(個人的には CInt よりも Integer.TryParse メソッドの方をおすすめします)で数値に変換してそれを代入する。
    と、明示的に記述する方が好ましいです。
    2009年5月24日 9:52
  • > クラス名.ID = Cint(Me.txt_MrrID.Text)
    >
    > としないと、値のセットができません。

    Public Property ID() As Integer と宣言しているのに、String 型の変数を代入することがうまく
    ないです。

    今回のようなケースでは、プロパティは単純に以下のようにして、代入する前に Me.txt_MrrID.Text
    が Nothing または "" なら 0 を代入し、それ以外なら Int32.TryParse メソッドで Int32 に変換で
    きるか調べた上で代入することをお勧めします。

    Public Property ID() As Integer
        Get
            Return IDvalue
        End Get
        Set(ByVal value As Integer)
            IDValue = value
        End Set
    End Property

    VB の自動型変換に頼らず、型を強く意識してプログラミングしてください。

    2009年5月24日 9:56
  • 文字列と数値の両方とっておくという手もあります。

    Class Sample
    
        ' IDの文字列
        Private _textID As String
        Public Property TextID() As String
            Get
                Return _textID
            End Get
            Set(ByVal value As String)
                _textID = value
    
                ' 値が変更されたら数値のほうに値を反映
                ' 数値に出来ない場合は0にする
                Dim output As Integer
                If Integer.TryParse(value, output) Then
                    _id = output
                Else
                    _id = 0
                End If
    
            End Set
        End Property
    
        ' IDの数値
        Private _id As Integer
        Public Property ID() As Integer
            Get
                Return _id
            End Get
            Private Set(ByVal value As Integer)
                _id = value
            End Set
        End Property
    End Class
    
    
    '使用例
    Dim s As New Sample
    
    ' 数字じゃないものあ入った時は0になる
    s.TextID = "abc"
    Console.WriteLine("{0}, {1}", s.TextID, s.ID)
    ' 数字が入ったときはIDはちゃんと数値が入ってる
    s.TextID = "123"
    Console.WriteLine("{0}, {1}", s.TextID, s.ID)
    

    かずき Blog:http://blogs.wankuma.com/kazuki/
    2009年5月24日 10:23
  • ご回答ありがとうございます。

    今まで、はっきりとしていなかったのは、フォームとプロパティでそれぞれどのあたりまでのチェックをかけるのか、という点でした。

    間違っていたら、ぜひ指摘していただきたいのですが、皆様の回答を見て感じたのは、プロパティに合致する型チェックまでは
    フォーム側で行っておき、その値のうちさらにチェックが必要な点(文字列の桁数や、数値の範囲、使用できる文字かどうかのチェックなど)
    をプロパティの側でチェックをする、と理解しておけばよいと思いました。

    そうすると、今まで自分がどうすればいいかと悩んでいた点について、方向性というものが見出せそうです。

    皆様、非常に参考になるご意見、ありがとうございました。
    2009年5月24日 12:11
  • 値の検証とかは、Windows Formだと仕組みが提供されてるのでそれを使うのも手です。
    詳細は、私の最初の投稿のURLとかがまとまってます~。


    かずき Blog:http://blogs.wankuma.com/kazuki/
    2009年5月24日 12:18