今回はこの記事の続き。
https://wetch.hatenablog.com/entry/2018/11/24/145716
標準モジュールからは見えないけど同じクラスの別インスタンスからは見える、都合のいいメソッドの書き方を探していると、こちらにヒントが。
thom.hateblo.jp
インターフェースを使うとそういうことができると書いてある。けど書き方は書いてないので自分で四苦八苦して、なんとかできそうなのでまとめとこうと思う。
自分が作りたいのは物理量クラスなんだけど、まずは練習として分数クラスでやってみた。どうせ物理量クラスでも使うし。
このクラスでやりたいことは、
- 内部変数としては、分数なので分子と分母(ともにLong型)を持つ。
- 標準モジュールでは分子、分母に直接アクセスできないようにする。
- でもクラスモジュール内では直接アクセスする必要がある。
ということ。
例えば足し算をするために、標準モジュールではこう書きたい:
sub 分数sample() Dim a as IFraction, b as IFraction, sum as IFraction ' IFractionは分数クラスのインターフェース Set a = New Fraction Set b = New Fraction Set sum = New Fraction a.SetFraction(1, 2) ' a = 1/2 b.SetFraction(1, 3) ' b = 1/3 set sum=a.plus(b) 'sum=a+b Debug.Print sum.toString end sub
で、インターフェースIFractionではこう書けばいいのかな?
Public Sub SetFraction(n As Long, d As Long) End Sub Public Function Plus(x As IFraction) As IFraction End Function Public Function toString() As String End Function
これで動くように、具象クラスFractionを書く必要がある。最初はこう書いてみた。
Implements IFraction Private nume_ As Long Private deno_ As Long Public Property Get Numerator() As Long Numerator = nume_ End Property Public Property Let Numerator(n As Long) nume_ = n End Property Public Property Get Denominator() As Long Denominator = deno_ End Property Public Property Let Denominator(d As Long) deno_ = d End Property Public Sub IFraction_SetFraction(n As Long, d As Long) nume_ = n deno_ = d End Sub Public Function IFraction_Plus(x As IFraction) As IFraction IFraction_Plus.Numerator = nume_ * x.Denominator + deno_ * x.Numerator IFraction_Plus.Denominator = deno_ * x.Denominator End Function Private Function IFraction_toString() As String IFraction_toString = nume_ & " / " & deno_ End Function
ところがこれでは動かない。IFraction_Plusのところで、xはIFraction型なのでNumeratorやDenominatorのプロパティが使えない。かと言って
Public Function IFraction_Plus(x As Fraction) As IFraction
とxをFraction型で宣言したら、インターフェースでIFraction型で宣言したのと不整合だって叱られる。
ここで四苦八苦して、ようやく閃いたのが次の書きかた:
Public Function IFraction_Plus(ix As IFraction) As IFraction Dim x As Fraction, plus As Fraction Set x = ix Set plus = New Fraction plus.Numerator = nume_ * x.Denominator + deno_ * x.Numerator plus.Denominator = deno_ * x.Denominator Set IFraction_Plus = plus End Function
いったんIFraction型で引数ixを取って、内部でFractiong型の別の変数xに格納し直した。
出力のほうも、最後に出力するIFraction型とは別にFraction型変数plusで計算をする。
とりあえずこれでちゃんと計算してるからいいのかな・・・?
あくまで自己流なので、正しいやり方が別にあるのかもしれないけど、これで進めてみる。