91

独自のクラスに引数を直接渡すオブジェクトをどのように構築できますか?

このようなもの:

Dim this_employee as Employee
Set this_employee = new Employee(name:="Johnny", age:=69)

これができないのは非常に煩わしく、これを回避するための汚いソリューションになってしまいます。

4

6 に答える 6

125

これは私が最近使っているちょっとしたトリックで、良い結果をもたらします。VBAでよく戦わなければならない人たちと共有したいと思います。

1.-各カスタム クラスにパブリック開始サブルーチンを実装します。私はすべてのクラスでこれを InitiateProperties と呼んでいます。このメソッドは、コンストラクターに送信する引数を受け入れる必要があります。

2.- factoryと呼ばれるモジュールを作成し、「Create」という単語に加えてクラスと同じ名前、およびコンストラクターが必要とするのと同じ入力引数を使用してパブリック関数を作成します。この関数は、クラスをインスタンス化し、ポイント (1) で説明した開始サブルーチンを呼び出して、受け取った引数を渡す必要があります。最後に、インスタンス化および開始されたメソッドを返しました。

例:

カスタムクラス Employee があるとしましょう。前の例のように、名前と年齢でインスタンス化する必要があります。

これが InitiateProperties メソッドです。m_name と m_age は、設定するプライベート プロパティです。

Public Sub InitiateProperties(name as String, age as Integer)

    m_name = name
    m_age = age

End Sub

そして今、ファクトリモジュールで:

Public Function CreateEmployee(name as String, age as Integer) as Employee

    Dim employee_obj As Employee
    Set employee_obj = new Employee

    employee_obj.InitiateProperties name:=name, age:=age
    set CreateEmployee = employee_obj

End Function

そして最後に、従業員をインスタンス化する場合

Dim this_employee as Employee
Set this_employee = factory.CreateEmployee(name:="Johnny", age:=89)

複数のクラスがある場合に特に便利です。モジュールファクトリにそれぞれの関数を配置し、 factory.CreateClassA (arguments)factory.CreateClassB(other_arguments)などを呼び出すだけでインスタンス化します。

編集

stenci が指摘したように、コンストラクター関数でローカル変数を作成することを避けることで、より簡潔な構文で同じことを行うことができます。たとえば、CreateEmployee 関数は次のように記述できます。

Public Function CreateEmployee(name as String, age as Integer) as Employee

    Set CreateEmployee = new Employee
    CreateEmployee.InitiateProperties name:=name, age:=age

End Function

どちらがいいです。

于 2013-03-05T12:43:23.953 に答える
40

各クラスのメンバーを呼び出すクラスごとFactoryに 1 つ (または複数)のコンストラクターを含む 1つのモジュールを使用します。Init

たとえば、Pointクラス:

Class Point
Private X, Y
Sub Init(X, Y)
  Me.X = X
  Me.Y = Y
End Sub

Lineクラス_

Class Line
Private P1, P2
Sub Init(Optional P1, Optional P2, Optional X1, Optional X2, Optional Y1, Optional Y2)
  If P1 Is Nothing Then
    Set Me.P1 = NewPoint(X1, Y1)
    Set Me.P2 = NewPoint(X2, Y2)
  Else
    Set Me.P1 = P1
    Set Me.P2 = P2
  End If
End Sub

そしてFactoryモジュール:

Module Factory
Function NewPoint(X, Y)
  Set NewPoint = New Point
  NewPoint.Init X, Y
End Function

Function NewLine(Optional P1, Optional P2, Optional X1, Optional X2, Optional Y1, Optional Y2)
  Set NewLine = New Line
  NewLine.Init P1, P2, X1, Y1, X2, Y2
End Function

Function NewLinePt(P1, P2)
  Set NewLinePt = New Line
  NewLinePt.Init P1:=P1, P2:=P2
End Function

Function NewLineXY(X1, Y1, X2, Y2)
  Set NewLineXY = New Line
  NewLineXY.Init X1:=X1, Y1:=Y1, X2:=X2, Y2:=Y2
End Function

このアプローチの良い点の 1 つは、式の中でファクトリ関数を簡単に使用できることです。たとえば、次のようなことが可能です。

D = Distance(NewPoint(10, 10), NewPoint(20, 20)

また:

D = NewPoint(10, 10).Distance(NewPoint(20, 20))

それはきれいです: ファクトリはほとんど何もせず、すべてのオブジェクトで一貫して行います。作成と各CreatorInitの 1 つの呼び出しだけです。

そして、かなりオブジェクト指向ですInit。関数はオブジェクト内で定義されます。

編集

これにより静的メソッドを作成できることを付け加えるのを忘れていました。たとえば、次のようなことができます (パラメータをオプションにした後):

NewLine.DeleteAllLinesShorterThan 10

残念ながら、オブジェクトの新しいインスタンスが毎回作成されるため、静的変数は実行後に失われます。行のコレクションと、この疑似静的メソッドで使用されるその他の静的変数は、モジュールで定義する必要があります。

于 2013-12-18T18:33:24.707 に答える
-2

別のアプローチ

クラス clsBitcoinPublicKey を作成するとします。

クラス モジュールで、実際のコンストラクターの動作を希望するように動作する ADDITIONAL サブルーチンを作成します。以下では、ConstructorAdjunct と名付けました。

Public Sub ConstructorAdjunct(ByVal ...)

 ...

End Sub

From the calling module, you use an additional statement

Dim loPublicKey AS clsBitcoinPublicKey

Set loPublicKey = New clsBitcoinPublicKey

Call loPublicKey.ConstructorAdjunct(...)

唯一のペナルティは余分な呼び出しですが、クラス モジュールにすべてを保持できるという利点があり、デバッグが容易になります。

于 2014-03-29T18:32:01.053 に答える