以下是我在命令按钮上得到的内容;它只是创建变量并尝试输出它们的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
Modeul1.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继承任何东西;他们只是被迫实现相同的接口(哇)
更糟糕的是,这是我真正希望是可纠正的,当涉及到参数传递时,他们似乎无法填充基类的对象。
我做错什么了吗?
Visual Basic 6不是学习"更纯粹"形式OOP的理想语言。VB6旨在实现一个非常混合的基于对象的编程版本,该版本围绕Microsoft组件对象模型(COM)世界,其接口继承方向。VB6不支持实现继承,这往往会使您想要的多态性难以实现。
我记得在VB6时代有一些技巧可以"绕过"(某种程度上)实现继承问题,尤其是在用基类的对象替换子类时。我记得的一个技巧是声明一个基接口类型的属性过程,该过程返回对"Me"的引用作为返回类型。这"欺骗"了运行时,使其提供到所需接口的转换。还有另一个魔术,可以通过在VB6的一个设计对话框中将属性的"过程编号"设置为-4,使其成为"defout"属性。
重点是什么?如果你真的想学习传统的OO编程,如果没有必要的话,不要尝试用VB6来学习。(至少)学习VB.NET、C#或Java。我并不是说,作为一个讨厌VB6的人——见鬼,知道这些愚蠢的细节很长一段时间以来都在买单——但要把它自己的小特质转化为对OOP的良好、基本的理解,这是一个很难解决的问题。
祝你好运!
您已经找到了如何修复错误,但我将提供"为什么"。
在VB6(和VB5等)中,有两种语法用于调用方法/函数/子例程/语句。第一个是:
MySubName arg1, arg2, arg3, arg4
Blech,我知道这是我对C和Java的偏见,但我喜欢在我的参数列表周围看到括号。那个sytax是这样的:
Call MySubName(arg1, arg2, arg3, arg4)
所以这两者是模棱两可的。
你遇到的不是电话的效果。您遇到的是非Call版本中不需要的括号的影响。括号强制在语句的其余部分之前计算括号中的语句/arg(想想运算的数学顺序)。
所以这个:
SomeSub (arg1)
是这样的:
temp = (arg1)
SomeSub temp
此外,VB6中的对象可以具有"默认属性"。这可以让你写这样的代码:
Dim name as String
name = txtName
使用.Text的默认属性,而不是将文本框对象引用分配给name,结果如下:
Dim name as String
name = txtName.Text
因此,当您尝试评估SomeSub (arg1)
时,我认为它会尝试定位并执行对象的默认属性,并将该值传递给SomeSub
。
好吧,我想明白了。
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.ID
添加到实现BaseObj
的类中的Property Get BaseObj_ID() As Integer
方法中。)