インターフェイスのメモ
インターフェイスについてメモ程度というか整理がついたのでまとめておく。
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も増えることは無い。
実は後輩がこのパターンで頭を悩ませているのを見て自分で考えてみた。いやぁ、勉強になった。