インターフェイスのメモ

インターフェイスについてメモ程度というか整理がついたのでまとめておく。

DBに担当者テーブルがあり、そのクラスと新規追加処理がある。これを使って新規入力画面から登録する。まぁ、年齢を持ってるDBはあまりないかも知れないがそれはスルーで。

Public Class OwnSystem

    '氏名
    Private m_Name As String = ""
    Public Property Name() As String
        Get
            Return Me.m_Name
        End Get
        Set(ByVal Value As String)
            Me.m_Name = Value
        End Set
    End Property

    '住所
    Private m_Address As String = ""
    Public Property Address() As String
        Get
            Return Me.m_Address
        End Get
        Set(ByVal Value As String)
            Me.m_Address = Value
        End Set
    End Property

    '生年月日
    Private m_Birthday As Date
    Public Property Birthday() As Date
        Get
            Return Me.m_Birthday
        End Get
        Set(ByVal Value As Date)
            Me.m_Birthday = Value
        End Set
    End Property

    '年齢
    Private m_Age As Integer
    Public Property Age() As Integer
        Get
            Return Me.m_Age
        End Get
        Set(ByVal Value As Integer)
            Me.m_Age = Value
        End Set
    End Property

End Class

Private Sub AddData(ByVal vData As OwnSystem)

		'本来はDBへの追加処理とか
    Trace.WriteLine("Name:" & vData.Name)
    Trace.WriteLine("Address:" & vData.Address)
    Trace.WriteLine("Birthday:" & vData.Birthday)
    Trace.WriteLine("Age:" & vData.Age)

End Sub

これは問題無い。
で、ある日機能拡張として、他システムから担当者を取り込みたくなったとする。テーブルは似ているが同じじゃない。クラスにするとこんな感じ。

Public Class SystemA

    '苗字
    Private m_Myoji As String = ""
    Public Property Myoji() As String
        Get
            Return Me.m_Myoji
        End Get
        Set(ByVal Value As String)
            Me.m_Myoji = Value
        End Set
    End Property

    '名前
    Private m_Namae As String = ""
    Public Property Namae() As String
        Get
            Return Me.m_Namae
        End Get
        Set(ByVal Value As String)
            Me.m_Namae = Value
        End Set
    End Property

    '住所
    Private m_Jyusyo As String = ""
    Public Property Jyusyo() As String
        Get
            Return Me.m_Jyusyo
        End Get
        Set(ByVal Value As String)
            Me.m_Jyusyo = Value
        End Set
    End Property

    '生年月日
    Private m_TanJyobi As Date
    Public Property TanJyobi() As Date
        Get
            Return Me.m_TanJyobi
        End Get
        Set(ByVal Value As Date)
            Me.m_TanJyobi = Value
        End Set
    End Property

End Class

これをなんとかAddDataメソッドに食わせたい。こんな時は次のようなインターフェイスを準備する。

Public Interface IOwnSystemAdd
    ReadOnly Property Name() As String
    ReadOnly Property Address() As String
    ReadOnly Property Birthday() As Date
    ReadOnly Property Age() As Integer
End Interface

AddDataメソッド中で代入は必要無い、むしろAddDataメソッドに入ってからプロパティの変更は不可能なようにReadOnly属性を付ける。で、AddDataメソッドの引き数をこのインターフェイスに変更する。さらにSystemAクラスにインターフェイスを着せる。「実装する」とかよりも「着せる」って表現が断然しっくり来る。変更後のソースは以下。

Public Class OwnSystem
    Implements IOwnSystemAdd

    '名前
    Private m_Name As String = ""
    Public Property Name() As String 
        Get
            Return Me.m_Name
        End Get
        Set(ByVal Value As String)
            Me.m_Name = Value
        End Set
    End Property

    '住所
    Private m_Address As String = ""
    Public Property Address() As String
        Get
            Return Me.m_Address
        End Get
        Set(ByVal Value As String)
            Me.m_Address = Value
        End Set
    End Property

    '生年月日
    Private m_Birthday As Date
    Public Property Birthday() As Date
        Get
            Return Me.m_Birthday
        End Get
        Set(ByVal Value As Date)
            Me.m_Birthday = Value
        End Set
    End Property

    '年齢
    Private m_Age As Integer
    Public Property Age() As Integer
        Get
            Return Me.m_Age
        End Get
        Set(ByVal Value As Integer)
            Me.m_Age = Value
        End Set
    End Property

#Region "IOwnSystemAddの実装"

    Public ReadOnly Property NameX() As String Implements IOwnSystemAdd.Name
        Get
            Return Me.Name
        End Get
    End Property

    Public ReadOnly Property AddressX() As String Implements IOwnSystemAdd.Address
        Get
            Return Me.Address
        End Get
    End Property

    Public ReadOnly Property BirthdayX() As Date Implements IOwnSystemAdd.Birthday
        Get
            Return Me.Birthday
        End Get
    End Property

    Public ReadOnly Property AgeX() As Integer Implements IOwnSystemAdd.Age
        Get
            Return Me.Age
        End Get
    End Property

#End Region

End Class



Public Class SystemA
    Implements IOwnSystemAdd

    '苗字
    Private m_Myoji As String = ""
    Public Property Myoji() As String
        Get
            Return Me.m_Myoji
        End Get
        Set(ByVal Value As String)
            Me.m_Myoji = Value
        End Set
    End Property

    '名前
    Private m_Namae As String = ""
    Public Property Namae() As String
        Get
            Return Me.m_Namae
        End Get
        Set(ByVal Value As String)
            Me.m_Namae = Value
        End Set
    End Property

    '住所
    Private m_Jyusyo As String = ""
    Public Property Jyusyo() As String
        Get
            Return Me.m_Jyusyo
        End Get
        Set(ByVal Value As String)
            Me.m_Jyusyo = Value
        End Set
    End Property

    '生年月日
    Private m_TanJyobi As Date
    Public Property TanJyobi() As Date
        Get
            Return Me.m_TanJyobi
        End Get
        Set(ByVal Value As Date)
            Me.m_TanJyobi = Value
        End Set
    End Property

#Region "IOwnSystemAddの実装"

    Public ReadOnly Property Name() As String Implements IOwnSystemAdd.Name
        Get
            Return Me.Myoji & Me.Namae
        End Get
    End Property

    Public ReadOnly Property Address() As String Implements IOwnSystemAdd.Address
        Get
            Return Me.Jyusyo
        End Get
    End Property

    Public ReadOnly Property Birthday() As Date Implements IOwnSystemAdd.Birthday
        Get
            Return Me.TanJyobi
        End Get
    End Property

    Public ReadOnly Property Age() As Integer Implements IOwnSystemAdd.Age
        Get
            'とりあえず
            Return Now.Year - Me.Birthday.Year
        End Get
    End Property

#End Region

End Class



Private Sub AddData(ByVal vData As IOwnSystemAdd)

    Trace.WriteLine("Name:" & vData.Name)
    Trace.WriteLine("Address:" & vData.Address)
    Trace.WriteLine("Birthday:" & vData.Birthday)
    Trace.WriteLine("Age:" & vData.Age)

End Sub

さっきまで処理できていたOwnSystemクラスがエラーになるので同じようにインターフェイスを着せている。が、インターフェイス実装部分のプロパティ名が適当な感じになってしまった。これでいいんだろうか?
いままでインターフェイスは定義してそれから実装という印象があったのだが、後から定義してクラス間の差を埋めるような使い方も出来るのだとわかった。他システムがどんな形になろうとAddDataメソッドには全く影響しない。Overloadも増えることは無い。
実は後輩がこのパターンで頭を悩ませているのを見て自分で考えてみた。いやぁ、勉強になった。