使用继承对象时传递基础对象类型

时间:2010-10-08 19:26:30

标签: vb.net oop

我有一个主要有两个对象的项目,都是从一个基础继承的。像这样:

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

上述功能不起作用,因为myVehicleVehicle,而不是Truck

有没有办法可以传递Vehicle类型并让IDE知道要使用哪种类型?或者我完全错过了更好的方法吗?

5 个答案:

答案 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应该将卡车作为参数,只有这样才有意义。