Passing the base type of an object when using an inherited

I have a project that has basically two objects, both inherit from the base. Like this:

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 

Simple enough, huh? Since I don’t know if the user will choose a car or truck, what I would like to do is just go through Vehicle .

So something like this:

 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 

It all works, but now I just want to pass v and use its properties. How:

 Sub SetFlat (myVehicle As Vehicle) myVehicle.IsFlatbed = True End Sub 

The above function does not work, because myVehicle is Vehicle , not Truck .

Is there a way to pass the type of Vehicle and find out which type to use the IDE? Or do I absolutely see no better way to do this?

+4
source share
5 answers

This can be done like this:

 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 a flatbed") Exit Sub End If Next Console.WriteLine(" so flatbed doesn't apply") End Sub End Module 

Conclusion:

 v is a Vehicles.Truck and now it a flatbed v is a Vehicles.Car so flatbed doesn't apply 
+2
source

Basically, when you call SetFlat , you know that your car has a property called IsFlatbed , right?

Then you must declare the Flattable interface that includes this property. The Truck class will implement this interface, and SetFlat sub will have a Flattable object as a parameter instead of a vehicle.

Edit:

How about this:

 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 
+3
source

I found two approaches that can help you.

More elegant is to force your subclass base to use a generic method without type inference. It might look something like this (I'm not a VB.Net programmer, so there may be some errors):

 Sub SetFlat(of T) (myVehicle As T) T.IsFlatbed = True End Sub // later you can just call SetFlat(Of Truct)(myVehicle) 

Of course, this means that you need to know the exact type of the myVehicle object before calling SetFlat. Also, SetFlat can only be called with classes that have the IsFlatbed property. Additional information on generics in VB.Net:
http://www.15seconds.com/issue/040526.htm
http://msdn.microsoft.com/en-us/library/w256ka79%28VS.80%29.aspx
Common Functions in VB.NET

The second (dirty) solution is to use .Net reflection to determine if the myVehicle object contains the IsFlatbed property. You can find more information about:
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
source

I decided to run Visual Studio and do some testing because my comments on the other answers would probably not make much sense. Assuming you have the following classes:

 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 

Another class may also have the following methods:

 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 

Thus, this allows you to go around the vehicle at your discretion, because you will not know until you see what type of vehicle you have in mind (car or truck). The SetFlat method at run time can determine which specific subclass of the vehicle it has passed and act accordingly. You just need to make sure that you apply the common vehicle object (v) to the new object of a more specific subclass after you have determined what type of subclass it has (either c for Car or t for Truck), otherwise the code will not compile because you are trying to invoke a method that does not exist on a universal type of vehicle, but only on certain subtypes of vehicles.

The biggest drawback that I see in this approach is that it can get tired if you have a lot of code. This is due to the fact that each method that you want to call will have to be checked to find out what type of a specific object of the vehicle it has passed, and to start a different set of routines depending on that particular type.

+2
source

I think you should give more detailed information about what you are trying to do ... In any case, in VB you have an operator to determine if an object is a type, that is, a typeof operator. You can check if v is a truck and use the translation operator (DirectCast, CType) to transfer v to Truck, for example

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

EDIT : SetFlat should take the "Truck" parameter, only that makes sense.

0
source

All Articles