2

这是我在命令按钮上的内容;它只是创建变量并尝试输出它们的 ID(应该是从基类继承的实例变量。)

Private Sub Command1_Click()
    Dim ball1 As Ball, ball2 As Ball
    Dim cube1 As Cube, cube2 As Cube

    Set ball1 = New Ball
    Set cube1 = New Cube
    Set cube2 = New Cube
    Set ball2 = New Ball

    MsgBoxTheID (ball1)  'errors; should be 0
    MsgBoxTheID (ball2)  'errors; should be 3
    MsgBoxTheID (cube1)  'errors; should be 1
    MsgBoxTheID (cube2)  'errors; should be 2

    Call ball1.MsgBoxID  ' works; displays 0
    Call ball2.MsgBoxID  ' works; displays 3
    Call cube1.MsgBoxID  ' works; displays 1
    Call cube2.MsgBoxID  ' works; displays 2

End Sub

模型1.bas:

Global globalID As Integer

Public Sub MsgBoxTheID(theObj As BaseObj)
    ' this function is meant to accept objects of type Ball, Cube, and BaseObj
    MsgBox theObj.ID
End Sub

BaseObj 类模块:

Public ID As Integer
Public isVisible As Boolean

Public Sub setVisiblity(newVis As Boolean)
    isVisible = newVis
End Sub

Public Sub MsgBoxID()
    MsgBox ID
End Sub

Private Sub Class_Initialize()
    ID = globalID
    globalID = globalID + 1
End Sub

球类模块:

Implements BaseObj
Private theObj As BaseObj
Public radius As Double

Private Property Let BaseObj_ID(ByVal RHS As Integer)
End Property
Private Property Get BaseObj_ID() As Integer
End Property
Private Property Let BaseObj_isVisible(ByVal RHS As Boolean)
End Property
Private Property Get BaseObj_isVisible() As Boolean
End Property

Public Sub MsgBoxID()
    Call theObj.MsgBoxID
End Sub

Private Sub BaseObj_MsgBoxID()
    Call theObj.MsgBoxID
End Sub

Public Sub BaseObj_setVisiblity(newVis As Boolean)
End Sub

Private Sub Class_Initialize()
    Set theObj = New BaseObj
End Sub

立方体类模块:

Implements BaseObj
Private theObj As BaseObj
Public sideLength As Double

Private Property Let BaseObj_ID(ByVal RHS As Integer)
End Property
Private Property Get BaseObj_ID() As Integer
End Property
Private Property Let BaseObj_isVisible(ByVal RHS As Boolean)
End Property
Private Property Get BaseObj_isVisible() As Boolean
End Property

Public Sub MsgBoxID()
    Call theObj.MsgBoxID
End Sub

Private Sub BaseObj_MsgBoxID()
    Call theObj.MsgBoxID
End Sub

Public Sub BaseObj_setVisiblity(newVis As Boolean)
End Sub

Private Sub Class_Initialize()
    Set theObj = New BaseObj
End Sub

有几件事我不喜欢,其中两件事我的印象是不可避免的:(1) 与 C++ 相比它是一团糟,以及 (2) Ball 和 Cube 类仅包含BaseObj 类型的对象。他们实际上并没有从 BaseObj 继承任何东西。他们只是被迫实现相同的接口(whoopty doo。)

更糟糕的是,这是我真正希望可以纠正的问题,当涉及到参数传递时,它们似乎无法填充基类的对象。

难道我做错了什么?

4

3 回答 3

4

Visual Basic 6 不是学习“更纯粹”的 OOP 形式的理想语言。VB6 旨在实现一个非常混合版本的基于对象的编程,它围绕 Microsoft 组件对象模型 (COM) 世界,其接口继承方向。VB6 不支持实现继承,这往往会使您正在寻找的那种多态性难以实现。

我记得 VB6 时代有一些技巧可以“解决”(某种程度)实现继承问题,尤其是在用基类的对象替换子类时。我记得的一个技巧是声明一个基接口类型的属性过程,它返回对“Me”的引用作为返回类型。这会“欺骗”运行时提供到所需接口的转换。通过在 VB6 的一个设计对话框中将其“过程编号”设置为 -4,还有另一个魔术技巧可以使属性成为“默认”属性。

重点?如果你真的想进入传统的 OO 编程,如果没有必要,不要尝试用 VB6 来学习它。升级到(至少)VB.NET、C# 或 Java。我并不是说作为 VB6 的仇恨者——见鬼,知道这些愚蠢的细节支付了很长一段时间的账单——但将其自身的小特质转化为对 OOP 的良好、基本的理解是一个难以破解的难题。

祝你好运!

于 2012-07-17T04:07:53.833 回答
3

你已经想出了如何解决这个错误,但我会贡献“为什么”。

在 VB6(和 VB5 等)中,调用方法/函数/子例程/语句有两种语法。第一个是这样的:

MySubName arg1, arg2, arg3, arg4

Blech,我知道这是我对 C 和 Java 的偏见,但我喜欢在我的参数列表周围看到括号。该语法是这样的:

Call MySubName(arg1, arg2, arg3, arg4)

所以这两者是等价的。

您遇到的不是呼叫的效果。您遇到的是非 Call 版本中不需要的括号的影响。括号强制其中的语句/参数在语句的其余部分之前进行评估(想想数学运算顺序)。

所以这:

SomeSub (arg1)

是这样的:

temp = (arg1) 
SomeSub temp

此外,VB6 中的对象可以具有“默认属性”。这使您可以编写如下代码:

Dim name as String
name = txtName

不是将文本框对象引用分配给名称,而是使用 .Text 的默认属性,结果如下:

Dim name as String
name = txtName.Text

因此,当您尝试评估时,SomeSub (arg1)我认为它会尝试定位并执行对象的默认属性并将该值传递给SomeSub.

于 2012-07-17T12:15:35.523 回答
0

嗯,我想通了,有点。

MsgBoxTheID (ball1)  'errors; should be 0
MsgBoxTheID (ball2)  'errors; should be 3
MsgBoxTheID (cube1)  'errors; should be 1
MsgBoxTheID (cube2)  'errors; should be 2

...需要更改为...

Call MsgBoxTheID (ball1)  'errors; should be 0
Call MsgBoxTheID (ball2)  'errors; should be 3
Call MsgBoxTheID (cube1)  'errors; should be 1
Call MsgBoxTheID (cube2)  'errors; should be 2

...即使MsgBoxTheID没有返回类型,这很奇怪,因为我一直认为Call这只是您可以用来丢弃返回值而无需声明变量的东西,如下所示:

dim unneededVar as Integer
unneededVar = FunctionNameThatReturnsAnInteger()

但我想不会。所以......我必须仔细阅读该Call语句正在做什么以使这个示例程序工作,但它现在肯定可以工作。(我还必须添加BaseObj_ID = theObj.IDProperty Get BaseObj_ID() As Integer正在实现的类中的方法BaseObj。)

于 2012-07-17T10:06:20.370 回答