尝试在 VB6 中学习多态性等,但我的代码没有做我想要的



以下是我在命令按钮上得到的内容;它只是创建变量并尝试输出它们的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方法中。)

相关内容

最新更新