我有一个主要有两个对象的项目,都是从一个基础继承的。像这样:
Public Class Vehicle
Property Model As String
Property Make As String
End Class
Public Class Truck
Inherits Vehicle
Property IsFlatbed As Boolean
End Class
Public Class Car
Inherits Vehicle
Property LeatherSeats As Boolean
End Class
很简单,嗯?因为我不知道用户是选择汽车还是卡车,我想做的只是绕过Vehicle
。
所以,像这样:
Public v As Vehicle
Sub WhichVehicle()
Select Case cmbVehicle.SelectedItem
Case Truck
v = New Truck
Case Car
v = New Car
End Select
SetFlat (v)
End Sub
这一切都有效,但现在我只想传递v
并使用它的属性。像:
Sub SetFlat (myVehicle As Vehicle)
myVehicle.IsFlatbed = True
End Sub
上述功能不起作用,因为myVehicle
是Vehicle
,而不是Truck
。
有没有办法可以传递Vehicle
类型并让IDE知道要使用哪种类型?或者我完全错过了更好的方法吗?
答案 0 :(得分:3)
基本上当你致电SetFlat
时,你知道你的车辆有一个名为IsFlatbed
的房产,对吗?
然后你应该声明一个包含这个属性的接口Flattable
。类Truck
将实现该接口,而SetFlat
sub将具有Flattable
对象作为参数而不是车辆。
编辑:
这个怎么样:
Public Interface IFlattable
Property IsFlatbed() As Boolean
End Interface
Public Class Truck
Inherits Vehicle
Implements IFlattable
Private _isFlatBed as Boolean
Public Property IsFlatbed() as Boolean Implements IFlattable.IsFlatbed
Get
Return _isFlatbed
End Get
Set(ByVal value as Boolean)
_isFlatbed = value
End Set
End Class
Public v As Vehicle
Sub WhichVehicle()
Select Case cmbVehicle.SelectedItem
Case Truck
v = New Truck
SetFlat (DirectCast(v, IFlattable))
Case Car
v = New Car
End Select
End Sub
Sub SetFlat (myVehicle As Flattable)
myVehicle.IsFlatbed = True
End Sub
答案 1 :(得分:2)
我找到了两种方法可以帮到你。
更优雅的是通过使用没有类型推断的泛型方法来强制您的基类子类化。 它可能看起来像(我不是VB.Net程序员,所以可能会有一些错误):
Sub SetFlat(of T) (myVehicle As T)
T.IsFlatbed = True
End Sub
// later you can just call
SetFlat(Of Truct)(myVehicle)
当然这意味着你需要在调用之前知道myVehicle对象的确切类型
SetFlat功能。此外,只能使用具有IsFlatbed属性的类调用SetFlat。
关于VB.Net中泛型的更多细节:
http://www.15seconds.com/issue/040526.htm
http://msdn.microsoft.com/en-us/library/w256ka79%28VS.80%29.aspx
Generic Functions in VB.NET
第二个(脏)解决方案是使用.Net反射来检测myVehicle对象是否包含IsFlatbed属性。您可以找到更多详细信息:
http://msdn.microsoft.com/en-us/magazine/cc163750.aspx
http://visualbasic.about.com/od/usingvbnet/a/proginfo.htm
http://www.eggheadcafe.com/community/aspnet/14/14989/reflection.aspx
答案 2 :(得分:2)
我决定启动Visual Studio并进行一些测试,因为我对其他答案的评论可能没有多大意义。假设您有以下类:
Public Class Vehicle
Public Property Model As String
Public Property Make As String
End Class
Public Class Truck : Inherits Vehicle
Public Property IsFlatbed As Boolean
End Class
Public Class Car : Inherits Vehicle
Public Property LeatherSeats As Boolean
End Class
您可以在另一个类中使用以下方法:
Private Sub WhichVehicle()
Select Case cmbVehicle.SelectedItem
Case Truck
v = New Truck
Case Car
v = New Car
End Select
SetFlat(v)
End Sub
Private Sub SetFlat(ByVal myVehicle As Vehicle)
If TypeOf myVehicle Is Car Then
Debug.WriteLine("This is a car")
Dim c As Car = DirectCast(myVehicle, Car)
c.LeatherSeats = False
ElseIf TypeOf myVehicle is Truck Then
Debug.WriteLine("This is a truck")
Dim t As Truck = DirectCast(myVehicle, Truck)
t.IsFlatbed = True
End If
End Sub
因此,这允许您按照自己的意愿传递车辆物体,因为在运行时您不会知道您正在处理的特定类型的车辆(汽车或卡车)。 SetFlat方法可以在运行时间期间确定它通过的车辆的特定子类,并相应地采取行动。在确定了哪种类型的子类(c为Car或t为Truck)之后,您必须确保将通用车辆对象(v)转换为更具体的子类的新对象。 ),否则代码将无法编译,因为您将尝试调用通用车辆类型上不存在的方法,但仅限于特定的车辆子类型。
我看到这种方法的最大缺点是,如果你有很多代码,它可能会开始变得乏味。这是因为您要调用的每个方法都必须检查它所传递的特定车辆对象的类型,并根据该特定类型运行一组不同的例程。
答案 3 :(得分:2)
这是实现这一目标的一种方式:
Imports System.Reflection
Module main_
Sub Main()
Dim t As New Truck
Dim c As New Car
Dim v As Vehicle
v = t
SetFlat(v)
v = c
SetFlat(v)
End Sub
Sub SetFlat(ByVal v As Vehicle)
Dim vehicletype As Type
Dim members() As PropertyInfo
vehicletype = v.GetType
members = vehicletype.GetProperties
Console.Write("v is a " & vehicletype.ToString)
For Each m As PropertyInfo In members
If m.Name = "IsFlatbed" Then
m.SetValue(v, True, Nothing)
Console.WriteLine(" and now it's a flatbed")
Exit Sub
End If
Next
Console.WriteLine(" so flatbed doesn't apply")
End Sub
End Module
输出:
v is a Vehicles.Truck and now it's a flatbed
v is a Vehicles.Car so flatbed doesn't apply
答案 4 :(得分:0)
我认为你应该提供一些关于你试图实现的更多细节......
无论如何,在VB中你有一个运算符来确定一个对象是否是一个类型,即typeof
运算符。您可以测试v是否是卡车并使用强制转换操作员(DirectCast,CType)将v投射到卡车,例如
Dim v as Vehicle
'...
If typeof v is Truck then SetFlat(DirectCast(v, Truck))
编辑:SetFlat应该将卡车作为参数,只有这样才有意义。