Передача базового типа объекта при использовании наследуемого - PullRequest
4 голосов
/ 08 октября 2010

У меня есть проект, который имеет в основном два объекта, оба наследуются от базы. Как это:

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 знать, какой тип использовать? Или я полностью упускаю лучший способ сделать это?

Ответы [ 5 ]

3 голосов
/ 08 октября 2010

Обычно, когда вы звоните SetFlat, вы знаете, что у вашего автомобиля есть свойство с именем IsFlatbed, верно?

Тогда вам следует объявить интерфейс Flattable, который включает это свойство.Класс Truck будет реализовывать этот интерфейс, а подпрограмма SetFlat будет иметь объект 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
2 голосов
/ 16 октября 2010

Это один из способов добиться этого:

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
2 голосов
/ 16 октября 2010

Я решил запустить 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 может определить во время выполнения, в каком конкретном подклассе транспортного средства он был пройден, и действовать соответственно. Вам просто нужно убедиться, что вы приводите общий объект транспортного средства (v) к новому объекту более определенного подкласса после того, как вы определили, какой это тип подкласса (c для Car или t для Truck ), иначе код не будет скомпилирован, потому что вы пытаетесь вызвать метод, который не существует для общего типа транспортного средства, но только для определенных подтипов транспортных средств.

Самым большим недостатком этого подхода является то, что он может стать утомительным, если у вас много кода. Это потому, что каждый метод, который вы хотите вызвать, должен будет проверить, какой тип конкретного объекта транспортного средства был передан, и запустить другой набор подпрограмм в зависимости от этого конкретного типа.

2 голосов
/ 13 октября 2010

Я нашел два подхода, которые могут вам помочь.

Более элегантный вариант - заставить вашу базу наследовать с помощью универсального метода без вывода типа.Это может выглядеть примерно так (я не программист 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функция.Также SetFlat может вызываться только с классами, которые имеют свойство IsFlatbed.Еще несколько подробностей о дженериках в VB.Net:
1007 *http://www.15seconds.com/issue/040526.htm
http://msdn.microsoft.com/en-us/library/w256ka79%28VS.80%29.aspx
Общие функции в 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

0 голосов
/ 11 октября 2010

Я думаю, вы должны дать более подробную информацию о том, что вы пытаетесь выполнить ... В любом случае, в VB у вас есть оператор, чтобы определить, принадлежит ли объект типу, то есть оператор typeof.Вы можете проверить, является ли v Грузовиком, и использовать оператор приведения (DirectCast, CType) для приведения v к Грузовику, например:

Dim v as Vehicle
'...
If typeof v is Truck then SetFlat(DirectCast(v, Truck))

EDIT : SetFlat должен принять Грузовик в качестве параметра, только это имеет смысл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...