この記事は、
第8回 アクセス修飾子を上手く使って情報を隠蔽しようの続きです。前回は、情報の隠蔽とアクセス修飾子について解説しました。今回は、インターフェイスについて解説します。
オブジェクト指向プログラミングと言えばクラスと思いがちですが、インターフェイスも有用なツールです。インターフェイスを一言で言うと、
オブジェクトが守るべき約束や契約を表すものです。従って、クラスの様に実装を継承する事は出来ませんが、その方がかえってよい時もあります。例えば、そのアプリケーションでは、オブジェクトに識別子が必要だったとします。この状況で、全てのオブジェクトを、識別子オブジェクトの子オブジェクトとして定義するのは不可能に近いでしょう。
.NETでは多重継承が出来ないので、Windowオブジェクトの子オブジェクトを、識別子オブジェクトの子に出来ません。
Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Friend Interface IIdentifier
ReadOnly Property Number() As Integer
End Interface
Friend Class MessageWindow
Inherits Window
Implements IIdentifier
'このウィンドウの名前
Private m_id As String
Public ReadOnly Property Number As Integer _
Implements IIdentifier.Number
Get
Return Me.m_id
End Get
End Property
'インスタンスを識別するための定義
Private Shared NextID As Integer
'Windowのサイズを指定するための定義
Private Shared random As Random =
New Random(DateTime.Now.Ticks Mod Integer.MaxValue)
'使用するメッセージ
Private m_message As String
Private Function CheckMessage(ByVal value As String) As Boolean
If value Is Nothing OrElse value.Length = 0 Then
Return False
Else
Return True
End If
End Function
Public Property Message() As String
Get
Return Me.m_message
End Get
Private Set(value As String)
If Me.CheckMessage(value) = False Then
Throw New ArgumentException(
"1文字以上の文字列を指定して下さい。")
End If
Me.m_message = value
End Set
End Property
'各種コントロール
Dim input As TextBlock
Dim text As TextBox
'メッセージを指定してインスタンスを生成する
Public Sub New(Optional ByVal msg As String = "Hello World")
'Windowの設定
Me.Height = random.Next(100, 1000)
Me.Width = random.Next(100, 1000)
Me.Message = msg
'ボタン上のコントロール
Me.input = New TextBlock()
text = New TextBox()
Dim panel As New StackPanel()
Dim createBtn As New Button()
createBtn.Content = "作成"
AddHandler text.KeyDown,
Sub(sender As Object, e As KeyEventArgs)
If e.Key = Key.Enter Then
createBtn.Focus()
e.Handled = True
End If
End Sub
Dim searchBtn = New Button()
searchBtn.Content = "番号検索"
AddHandler searchBtn.Click, AddressOf SearchWindow
Dim nameBtn As New Button()
nameBtn.Content = "番号は?"
AddHandler nameBtn.Click,
Sub(sender As Object, e As RoutedEventArgs)
MessageBox.Show(
"私は" & Me.Number & "号",
"識別子",
MessageBoxButton.OK,
MessageBoxImage.Information)
e.Handled = True
End Sub
Dim endBtn As New Button()
endBtn.Content = "終了"
AddHandler endBtn.Click, Sub() Application.Current.Shutdown()
panel.Children.Add(input)
panel.Children.Add(text)
panel.Children.Add(createBtn)
panel.Children.Add(searchBtn)
panel.Children.Add(nameBtn)
panel.Children.Add(endBtn)
'ボタン
Dim btn = New Button()
btn.Content = panel
Me.Content = btn
AddHandler btn.Click, Sub() Me.CreateWindow()
AddHandler btn.KeyDown, Sub() text.Focus()
'その他の処理
Me.SetMessages()
Me.m_id = MessageWindow.NextID
MessageWindow.NextID += 1
End Sub
'指定した番号を持つウィンドウを検索
Private Sub SearchWindow(sender As Object, e As RoutedEventArgs)
Dim value As Integer
If Integer.TryParse(text.Text, value) = True Then
For Each win In Application.Current.Windows
Dim w As MessageWindow = CType(win, MessageWindow)
If w.Number = value Then
MessageBox.Show(
"見つかりました♪",
"検索結果",
MessageBoxButton.OK,
MessageBoxImage.Information)
e.Handled = True
w.Activate()
Exit Sub
End If
Next
End If
MessageBox.Show(
"指定のウィンドウはありません。",
"検索結果",
MessageBoxButton.OK,
MessageBoxImage.Exclamation)
e.Handled = True
End Sub
'新しいウインドウを作成する
Private Sub CreateWindow()
Dim win As MessageWindow
If Me.CheckMessage(Me.text.Text) = False Then
win = New MessageWindow()
Else
win = New MessageWindow(Me.text.Text)
End If
win.Show()
Dim btn As Button = CType(win.Content, Button)
btn.Focus()
End Sub
'指定されたメッセージを各種要素に反映する
Private Sub SetMessages()
Dim str As String = Me.Message
Me.Title = str
input.Text = str
End Sub
End Class
前のサンプルに、識別子を使ってウィンドウを検索する機能を追加しました。今回のサンプルでは、あまり識別子が有効利用されていません。ですが、識別子インターフェイスを使って、Window以外にも識別子をつけて検索できるように拡張するのは簡単です。これが可能になるのもインターフェイスのお陰です。
もっと成功例を知りたい人は、LINQを思い浮かべるとよいと思います。LINQは、インターフェイスと拡張メソッドを上手く組み合わせています。他には、.NETフレームワークのコレクションオブジェクト群を調べてみるとよいでしょう。インターフェイスが上手に使用されています。
インターフェイスは極めて便利なツールですが多様は禁物です。特に、外部に公開するインターフェイスは慎重に検討しましょう。何故ならば、
一度公開したインターフェイスを変更するのは大変だからです。古くからVBを使用している方は、COMプログラミングを思いだせばよくわかると思います。
インターフェイスのアクセス修飾子は、基本的に
Friendにしておきましょう。そうすれば、同僚に怒られるぐらいで済みます。慎重に設計をしていても、仕様変更はあります。その時の影響が最小限になるように、常に気をつけましょう。
テーマ : プログラミング
ジャンル : コンピュータ