HumbleBeginnings
HumbleBeginnings

Reputation: 1019

How Do I Create an Extension of a Single Class Property

I have a primitive Class that looks like this:

Public Class BaseGeoData
    Property GeoOrigin As String
    Property GeoDestination As String
    Property TravelDistance As Double?
    Property TravelTime As Double?

    Public Sub New()
    End Sub
End Class

Public Class GeoData
 Inherits BaseGeoData
   Public Sub New(geoOrigStr As String, geoDestStr As String)
       GeoOrigin = geoOrigStr
       GeoDestination = geoDestStr
       TravelDistance = 5000      'in meters
       TravelTime = 360           'in minutes
   End Sub
End Class

I want to be able to add 2 extensions that will return converted values like this:

TravelDistance.ToMiles()   
TravelTime.ToHours()

When I add a Module to extend the class, it offers the extension to the entire class, most properties of which will never use the extension. How can I just offer the extensions to the properties that need them?

Upvotes: 1

Views: 264

Answers (3)

Fabio
Fabio

Reputation: 32463

Introduce own type of "Unit" for measurement values

Public MustInherit Class Unit
    Public ReadOnly Property Value As Double

    Public MustOverride ReadOnly Property Name As String

    Public Sub New(value As Double)
        Me.Value = value
    End Sub

    Public Overrides Function ToString() As String
        Return $"{Value} {Name}"
    End Function
End Class

Public Class Meter
    Inherits Unit

    Public Sub New(value As Double)
        MyBase.New(value)
    End Sub

    Public Overrides ReadOnly Property Name As String
        Get
            Return "m"
        End Get
    End Property
End Class

Public Class Mile
    Inherits Unit

    Public Sub New(value As Double)
        MyBase.New(value)
    End Sub

    Public Overrides ReadOnly Property Name As String
        Get
            Return "mi"
        End Get
    End Property
End Class

And extension methods for creating unit and convertions

Public Module UnitConversions

    <Extension>
    Public Function Meters(value As Integer) As Meter
        Return New Meter(value)
    End Function

    <Extension>
    Public Function Miles(value As Integer) As Mile
        Return New Mile(value)
    End Function

    <Extension>
    Public Function ToMiles(meters As Meter) As Mile
        Dim miles = meters.Value * 0.00062137
        Return New Mile(miles)
    End Function

    <Extension>
    Public Function ToMeters(miles As Mile) As Meter
        Dim meters = miles.Value * 1609.344
        Return New Meter(meters)
    End Function
End Module

Then you can use value in more readable manner

TravelDistance = 5000.Meters() ' meters

' Conversion
geoData.TravelDistance.ToMiles() ' miles

Console.WriteLine(geoData.TravelDistance) ' print 3.10685 mi

Upvotes: 1

Zeddy
Zeddy

Reputation: 2089

I really like Plutonix's resolution and is the same one I would go for first.

Its simple and resolves your initial problem.

Public Class BaseGeoData

  Property GeoOrigin As String
  Property GeoDestination As String
  Property TravelDistance As Double?
  Property TravelTime As Double?

  Public Sub New()
  End Sub

End Class


Public Class GeoData
  Inherits BaseGeoData

  Public Sub New(geoOrigStr As String, geoDestStr As String)
    GeoOrigin = geoOrigStr
    GeoDestination = geoDestStr
    TravelDistance = 5000      'in meters
    TravelTime = 360           'in minutes
  End Sub

  Function DistanceMiles() As Double
    DistanceMiles = (TravelDistance/1609.344)
  End Function

  Function TimeHours() As Double
    DistanceMiles = (TravelTime /60)
  End Function

End Class

Upvotes: 0

Gabriel
Gabriel

Reputation: 1942

You can only add extension methods into types (i.e. classes).

TravelDistance is of type Double? so you have to add an extention method into Double?.

Note that it would make the method available for every Double?, which may not be something you want.

Upvotes: 0

Related Questions