VB.NET Creating a class with optional input


Keywords:vb.net 


Question: 

I'm trying to learn more about Object Orientated Programming.

I'm trying to create a class that represents a Conical object like in this image.

enter image description here

A : Connection diameter B : Diameter C : Height

But for me there are some differences when choosing a cone

1) Is the cone connection going to be larger than the diameter you have a expanding cone else a reduction cone. For this I created a read-only property based on an Enum that is set in the constructor. This is set while Creating the cone object and is fixed.

2) How do you want to dimension it. The image has 3 dimensions, but there is a forth one that is a angle. If the height is the leading dimension, the angle should be calculated, If the angle is a leading dimension the height should be calculated. Also for this I created a read-only property based on an Enum that is set in the constructor.

But how should I mark my properties? In one case the Height should be read-only and in the other the angle. How do you handle a situation such as this?

Public Class Cone

    Public ReadOnly Property ConeType As ConeTypeEnum

    Public Enum ConeTypeEnum
        kExpansion = 1
        kReduction = 2
    End Enum

    Public ReadOnly Property DimensionType As DimensionTypeEnum

    Public Enum DimensionTypeEnum
        kAngle = 1
        kHeight = 2
    End Enum

    Public Property Height As Double
    Public Property Diameter As Double
    Public Property ConnectionDiameter As Double
    Public Property Angle As Double

    Public Sub New(ByVal oConeType As ConeTypeEnum,
                   ByVal oDimensionType As DimensionTypeEnum)

        ConeType = oConeType
        DimensionType = oDimensionType

    End Sub

End Class

3 Answers: 

Here's what I'd do:

Determine the cone type property dynamically from the current A and B in a read-only property. This - as I understand it - is only an indicator of what cone-type you have.

All other properties can be read/write, updating the respective other properties. For example. If the user changes the angle, recalculate the height. If the user changes the height, recalculate the angle, etc.

In case you really want to set the cone-type, I'd do it when calling the constructor. Then change the other properties so that they throw an exception in case A and B don't fit the current cone-type.

Another way would be to define an Interface ICone with all the required properties and from that derive to classes ExpansionCone and ReductionCone that implement the getters/setters accordingly.



Here is what I would do :

Public Class Cone

    'First we have our dimensions
    Public Property Height As Double 'C on your graph
    Public Property DiameterUp As Double 'A on your graph
    Public Property DiameterDown As Double 'B on your graph

    'The cone Type can be calculated following the dimensions
    Public ReadOnly Property ConeType As ConeTypeEnum
        Get
            If _diameterDown > _diameterUp Then
                Return ConeTypeEnum.kReduction
            ElseIf _diameterDown < _diameterUp Then
                Return ConeTypeEnum.kExpansion
            End If
            'If they are equal it is a cylinder
            Return ConeTypeEnum.kCylinder
        End Get
    End Property

    Public Enum ConeTypeEnum
        kExpansion = 1
        kReduction = 2
        kCylinder = 3
    End Enum

    'The angle is just recalculated everytime
    Public Property Angle As Double
        Get
            Return 'Calculate here the angle value from the other dimensions
        End Get
        Set(value As Double)
            'Calculate here the dimension values according the value specified for the angle
        End Set
    End Property

    Public Sub New(Height As Double, DiameterUp As Double, DiameterDown As Double)
        Me.Height = Height
        Me.DiameterUp = DiameterUp
        Me.DiameterDown = DiameterDown
    End Sub
End Class


I would calculate the height or angle dynamically based on if the user is providing an angle or a height. Like Martin, I would get the type of cone dynamically. I would also put the New function private to prevent people from creating an empty code and instead have shared (factory) functions. Since a cone can be created with an angle or a height, the user of your class will have to call the proper function to create the object.

Cone.GetConeByAngle(...)
Cone.GetConeByHeight(...)

With the custom property for Height and Angle calculating the other value. Anyone can change both the height or the angle later with everything calculated properly.

Since I don't have time to look an the math, I left CalculateAngle and CalculateHeight empty.

I don't know why you put "k" are the beginning of your enum values.

Public Class Cone

    Public Enum ConeTypeEnum
        Expansion = 1
        Reduction = 2
        Cylinder = 3
    End Enum

    Private _height As Double
    Private _angle As Double

    Public Property Diameter As Double
    Public Property ConnectionDiameter As Double

    Public Property Height As Double
        Get
            Return _height
        End Get
        Set(value As Double)
            _height = value
            CalculateAngle()
        End Set
    End Property

    Public Property Angle As Double
        Get
            Return _angle
        End Get
        Set(value As Double)
            _angle = value
            CalculateHeight()
        End Set
    End Property

    Public ReadOnly Property ConeType As ConeTypeEnum
        Get
            If Diameter > ConnectionDiameter Then
                Return ConeTypeEnum.Reduction
            ElseIf Diameter < ConnectionDiameter Then
                Return ConeTypeEnum.Expansion
            End If

            'If they are equal it is a cylinder
            Return ConeTypeEnum.Cylinder
        End Get
    End Property

    Private Sub New()

    End Sub

    Public Shared Function GetConeByAngle(ByVal angle As Double, ByVal diameter As Double, ByVal connectionDiameter As Double)

        Dim newCone As New Cone

        newCone.Diameter = diameter
        newCone.ConnectionDiameter = connectionDiameter
        newCone.Angle = angle

        Return newCone
    End Function

    Public Shared Function GetConeByHeight(ByVal height As Double, ByVal diameter As Double, ByVal connectionDiameter As Double)

        Dim newCone As New Cone

        newCone.Diameter = diameter
        newCone.ConnectionDiameter = connectionDiameter
        newCone.Height = height

        Return newCone
    End Function

    Private Sub CalculateAngle()
        ' Calculate angle base on height
        _angle = 0
    End Sub

    Private Sub CalculateHeight()
        ' Calculate height base on angle
        _height = 0
    End Sub

End Class