とりあえず作ってみた。
東方算程譚:イベント連鎖
参照先ではコントロールになっていましたが、基本的には同じなはずなので、実装部分だけイメージしてみました。
書かれてある言葉のとおりに作ろうとしたんですが、
[Visual Basic]
Imports System
Imports System.Collections.Generic
Public Class Currency
Implements IComparable(Of Currency)
Enum CurrencyType
PaperMoney
Coin
End Enum
Private _type As CurrencyType
' 貨幣の種類だよ。
Public ReadOnly Property Type() As CurrencyType
Get
Return _type
End Get
End Property
Private _currencyUnit As Integer
' 貨幣単位だよ。
Public ReadOnly Property CurrencyUnit() As Integer
Get
Return _currencyUnit
End Get
End Property
Private _calcResult As Integer
' 計算の結果だよ。
Public ReadOnly Property CalcResult() As Integer
Get
Return _calcResult
End Get
End Property
' コンストラクタ。
Public Sub New(ByVal currencyUnit As Integer, ByVal type As CurrencyType)
If currencyUnit <= 0 Then
Throw New ArgumentOutOfRangeException("そんな貨幣ないよ!")
End If
Me._currencyUnit = currencyUnit
Me._calcResult = -1
Me._type = type
End Sub
' 計算するよ。
Public Sub Calc(ByVal price As Integer)
If price < 0 Then
Throw New ArgumentOutOfRangeException("負はイヤ!")
End If
Me._calcResult = price \ Me.CurrencyUnit
Dim leftOvers As Integer = price Mod Me.CurrencyUnit
Me.OnThroughLeftOvers(leftOvers)
End Sub
' 横流しイベント!
Public Event ThroughLeftOvers(ByVal price As Integer)
' 横流しイベントを発生させるメソッド。
Protected Sub OnThroughLeftOvers(ByVal price As Integer)
' そりゃ!
RaiseEvent ThroughLeftOvers(price)
End Sub
' ソートに使うなり。
Public Function CompareTo(ByVal other As Currency) As Integer Implements System.IComparable(Of Currency).CompareTo
If other Is Nothing Then
Throw New ArgumentNullException("other")
End If
Return Me._currencyUnit - other._currencyUnit
End Function
End Class
ここがよくわからなくて・・・。戻り値のあるデリゲートってイベントで使用できましたっけ?なんか勘違いしてるのかなぁ。
int 計算(int price) ってメソッドと、
int XXX(int price) をdelegateとするevent: 横流しを持ってます。
で、以下のように使用してみると。
フゥ・・・。一応出力は、
Public Class Program
_
Public Shared Sub Main()
' 貨幣単位でつくるよ!
Dim tenThousand As New Currency(10000, Currency.CurrencyType.PaperMoney)
Dim fiveThousand As New Currency(5000, Currency.CurrencyType.PaperMoney)
Dim OneThousand As New Currency(1000, Currency.CurrencyType.PaperMoney)
Dim fiveHundred As New Currency(500, Currency.CurrencyType.Coin)
Dim oneHundred As New Currency(100, Currency.CurrencyType.Coin)
Dim fifty As New Currency(50, Currency.CurrencyType.Coin)
Dim ten As New Currency(10, Currency.CurrencyType.Coin)
Dim five As New Currency(5, Currency.CurrencyType.Coin)
Dim one As New Currency(1, Currency.CurrencyType.Coin)
' ちょっとした小道具。
Dim list As New List(Of Currency)
' せかせか格納するのであります。
list.Add(tenThousand)
list.Add(fiveThousand)
list.Add(OneThousand)
list.Add(fiveHundred)
list.Add(oneHundred)
list.Add(fifty)
list.Add(ten)
list.Add(five)
list.Add(one)
' 降順に。
list.Sort()
list.Reverse()
' イベントハンドラを関連付ける。
For i As Integer = 0 To list.Count - 2
AddHandler list.Item(i).ThroughLeftOvers, AddressOf list.Item(i + 1).Calc
Next
' お勘定
Dim price As Integer = 23456
' 計算しなさ〜い。
list.Item(0).Calc(price)
' 計算結果を出力しましょ。
Program.Output(price, list)
End Sub
Private Shared Sub Output(ByVal price As Integer, ByVal list As List(Of Currency))
Console.WriteLine("{0}円は", price.ToString)
For i As Integer = 0 To list.Count - 1
' 使わないのは出力しない方向で。
If list.Item(i).CalcResult <= 0 Then
Continue For
End If
' 貨幣の呼び方。
Dim currencyTypeName As String
' 紙幣は「札」、硬貨は「玉」で。
If list.Item(i).Type = Currency.CurrencyType.PaperMoney Then
currencyTypeName = "札"
Else
currencyTypeName = "玉"
End If
Console.WriteLine("{0}円{1}が{2}枚,", list.Item(i).CurrencyUnit.ToString.PadLeft(5, " "c), currencyTypeName, list.Item(i).CalcResult.ToString)
Next
Console.WriteLine("必要っぽいよ。")
End Sub
End Class
合ってるかな。
23456円は
10000円札が2枚,
1000円札が3枚,
100円玉が4枚,
50円玉が1枚,
5円玉が1枚,
1円玉が1枚,
必要っぽいよ。