【问题标题】:How have you dealt with the lack of constructors in VB6?您如何处理 VB6 中缺少构造函数的问题?
【发布时间】:2024-01-02 00:17:01
【问题描述】:

VB6 类没有参数化构造函数。您为此选择了什么解决方案?使用工厂方法似乎是显而易见的选择,但让我感到惊讶!

【问题讨论】:

  • 缺乏构造函数并不是说 IMO 的好方法。 VB6 确实 确实有无参数构造函数(Class_Initialize 方法)。它没有的是参数化构造函数。

标签: class vb6 constructor


【解决方案1】:

我通常坚持使用工厂方法,将相关类的“构造函数”放在同一个模块中(.BAS 扩展名)。遗憾的是,这远非最佳,因为您不能真正限制对 VB6 中正常对象创建的访问——您只需要指出仅通过工厂创建对象即可。

更糟糕的是必须在实际对象和工厂方法之间跳转,因为 IDE 本身的组织充其量是繁琐的。

【讨论】:

  • 或者将工厂方法添加到类本身呢?将工厂方法放在模块中使它们特定于应用程序。
  • @Dabblernl - 但是你必须让它们等同于Java的public static,对吧? VB6 没有静态方法。
  • 好吧,不需要静态类。您必须创建一个实例来访问工厂方法,但是由于您不使用可以接受的对象的依赖关系,恕我直言
  • @Dabblernl - 啊,我明白了。这实际上听起来像是一个更好的解决方案,我必须尝试一下。
  • +1。值得一提的是一个特例。如果您的类是在另一个组件中定义的(例如 ActiveX DLL),您可以限制对正常对象创建的访问。使类 PublicNotCreatable 强制客户端使用您的工厂方法。 msdn.microsoft.com/en-us/library/aa242107(VS.60).aspx
【解决方案2】:

使用可用的类初始化器怎么样?这就像一个无参数的构造函数:

Private Sub Class_Initialize()
    ' do initialization here

End Sub

【讨论】:

  • 它不接受任何参数的事实使它作为构造函数毫无用处。它实际上只允许您设置一些东西,但不能真正初始化对象的状态。
  • 抱歉,我的问题不清楚。我的意思是如何解决只有一个无参数构造函数的问题:Class_Initialize
  • 发布此答案后问题已更改。
【解决方案3】:

我混合使用工厂函数(在父类中),然后创建对象实例并调用 Friend Init() 方法。

班级CObjects:

Public Function Add(ByVal Param1 As String, ByVal Param2 As Long) As CObject
  Dim Obj As CObject
  Set Obj = New CObject
  Obj.Init Param1, Param2
  Set Add = Obj
End Function

班级CObject:

Friend Sub Init(ByVal Param1 As String, ByVal Param2 As Long)
  If Param1 = "" Then Err.Raise 123, , "Param1 not set"
  If Param2 < 0 Or Param2 > 15 Then Err.Raise 124, , "Param2 out of range"

  'Init object state here
End Sub

我知道Friend 范围不会对项目产生任何影响,但它作为一个警告,它仅供内部使用。 如果这些对象通过 COM 公开,则无法调用 Init 方法,并将类设置为 PublicNotCreatable stops it being created

【讨论】:

    【解决方案4】:

    这个解决方案不是完美的,但是,这就是我最终为我的一些遗留项目所做的事情。它在存储方面有点节省内存,但是仅仅查找某些东西肯定比其他方式需要更多的时间,尤其是对于巨大的结构。

    假设你需要实现以下,

    type user
     id as long
     name as String
     desc as String
    end type
    

    但请注意,VB6 本身就支持字符串。所以不要使用结构,而是使用“假结构”功能,例如

    Public Function user_raw(ByVal id as Long, ByRef name as String, ByRef desc as String) as String
     Const RAW_DELIM as String = "|"
     user_raw = cstr(id) & RAW_DELIM & name & RAW_DELIM & desc 
    End Function
    

    因此,您将获得按值传递(因此可堆叠成数组或多行字符串),由字符串组成的“假结构”,例如

    1|Foo|VB的老大

    2|巴|Foo的徒弟

    所以构造也算作执行to_string() 的粗略方式。从好的方面来说,这种存储几乎可以立即转换为 Markdown 表语法。

    稍后,您可以通过执行以下操作从结构中检索数据,

    Public const RAW_DELIM as String = "|"
    Public Const POS_USER_ID = 0
    Public Const POS_USER_NAME = 1
    Public Const POS_USER_DESC = 2
    '...
    public function get_raw_variable(byref user as String, byval var as integer) as String
     dim buf() as String
    
     buf = SPLIT(user, "|")
     Assert ubound(buf) <= var
     get_raw_variable = buf(var)
    end function
    

    检索肯定是低效的,但几乎是您可以拥有的最好的。祝你好运

    【讨论】: