试图在VB6中学习多态性等,但我的代码没有';我不能做我想做的事

试图在VB6中学习多态性等,但我的代码没有';我不能做我想做的事,vb6,parameters,polymorphism,Vb6,Parameters,Polymorphism,这是我在命令按钮上得到的信息;它只是创建变量并尝试输出它们的ID(应该是从基类继承的实例变量) 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类模块

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

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
球类模块:

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)事实上,球和立方体类仅<强>包含< /强>对象的BaseObjo类型。他们实际上并没有从BaseObj继承任何东西;他们只是被迫实现相同的接口(whoopty-doo)

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


我做错什么了吗?

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

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

重点是什么?如果你真的想进入传统的面向对象编程,如果不需要的话,不要尝试用VB6来学习。向上移动到(至少)VB.NET、C#或Java。我并不是说,作为一个讨厌VB6的人——见鬼,知道这些愚蠢的细节已经花了很长时间——但要把自己的一些小特质转化为对OOP的良好、基本的理解,这是一个很难破解的难题


祝你好运

嗯,我算是弄明白了

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
的类中将
BaseObj\u ID=theObj.ID
作为整数添加到
属性Get BaseObj\u ID()
中)

您已经找到了修复错误的方法,但我将提供“为什么”

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

MySubName arg1, arg2, arg3, arg4
Blech,我知道这是我对C和Java的偏见,但我喜欢在参数列表中看到括号。那就是:

Call MySubName(arg1, arg2, arg3, arg4)
因此,这两者是等价的

你遇到的不是电话的效果。您遇到的是非调用版本中不需要的括号的影响。括号强制在语句的其余部分之前对其中的语句/arg求值(考虑运算的数学顺序)

因此:

SomeSub (arg1)
是这样的:

temp = (arg1) 
SomeSub temp
Dim name as String
name = txtName
Dim name as String
name = txtName.Text
此外,VB6中的对象可以具有“默认属性”。这使您可以编写如下代码:

temp = (arg1) 
SomeSub temp
Dim name as String
name = txtName
Dim name as String
name = txtName.Text
使用.Text的默认属性,而不是将textbox对象引用指定给name,结果如下:

temp = (arg1) 
SomeSub temp
Dim name as String
name = txtName
Dim name as String
name = txtName.Text

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

只是一个简短的提示。BaseObj有一个名为
setVisiblity
的方法。但它是redundent,因为您还有一个公共的isVisible变量。当您在类中将某个对象声明为公共时,它将成为其公共接口的一部分。习惯于将这些类变量声明为Private。这也会清理代码。@tcarvin是的,这只是我第一次尝试使用多态性时扔掉的一些垃圾。+1这里有一些到解决方法描述的链接。这里有一些关于Call语句和括号含义的解释,我不觉得自己很愚蠢吗可悲的是,我知道得更多,但我想我已经多年没有犯那个错误了,根据对错误的描述,我无法确定真正的问题。@Michael哦,不,这一点都不明显。特别是如果你用多种语言写作,来回走动。最常见的错误是忘记使用
Set
。这就是为什么我总是使用
Call
语法。它是明确的,可以防止意外评估。