I have a class, it looks like this:
Public Class DataPoint
Private _data As Integer
Private _locInText As Integer
Private _searchValue As String
Property Data As Integer
Get
Return _data
End Get
Set(value As Integer)
_data = value
End Set
End Property
Property LocInText As Integer
Get
Return _locInText
End Get
Set(value As Integer)
_locInText = value
End Set
End Property
Property SearchValue As String
Get
Return _searchValue
End Get
Set(value As String)
_searchValue = value
End Set
End Property
End Class
I then create another class using this class.
Public Class PaintData
Public Time As TimeSpan
Public Color As DataPoint
Public Job As New DataPoint
Public MaxCurrent As New DataPoint
End Class
I want to create default values of some of the properties, namly SearchValue and LocInText. To me, it makes sense to do this inside the class definition, because these are essentially constants.
Q1. Should I be doing it this way? If not, what is the proper technique.
Q2. I can't get the syntax right. Can you help?
Public Class PaintData
Public Time As TimeSpan
Public Color As DataPoint
Public Job As New DataPoint
Public MaxCurrent As New DataPoint
Color.LocInText = 4 '<----Declaration expected failure because I'm not in a method
Job.LocInText = 5 '<----Declaration expected failure because I'm not in a method
End Class
Thanks all
Give DataPoint a constructor:
Public Class DataPoint
Private _data As Integer
Private _locInText As Integer
Private _searchValue As String
Public Sub New(locInText as Integer)
_locInText = locInText
End Sub
'...
End Class
And use that:
Public Class PaintData
Public Time As TimeSpan
Public Color As New DataPoint(4)
Public Job As New DataPoint(5)
Public MaxCurrent As New DataPoint(6)
End Class
Alternatively you could use
Public Property Color As DataPoint = New DataPoint With {.LocInText = 4}
in your class definition. This syntax is arguably more readable than the constructor syntax.
Related
I am working on a script to help me create geometry in 3D software based on user input and I wanted to approach the problem with classes. I have 3 levels of structures, points, curves and surfaces so I want to create a class for each, where the next level structure inherits the lower one.
So for example class cPoint have 4 properties: x,y,z,id. Further, the class cCurve has only 2 properties: id and points, and the same for surfaces.
Now my question is: I implemented class cPoint as follows:
Private x_ As Double
Private y_ As Double
Private z_ As Double
Private id_ As Long
Public Property Let X(ByVal value As Double)
x_ = value
End Property
Public Property Let Y(ByVal value As Double)
y_ = value
End Property
Public Property Let Z(ByVal value As Double)
z_ = value
End Property
Public Property Let ID(ByVal value As Long)
id_ = value
End Property
Public Property Get X() As Double
X = x_
End Property
Public Property Get Y() As Double
Y = y_
End Property
Public Property Get Z() As Double
Z = z_
End Property
Public Property Get ID() As Long
ID = id_
End Property
and everything is fine here. And here I have class cCurve implemented:
Implements cPoint
Private id_ As Long
Private point_ As Collection
Public Property Let ID(ByVal value As Long)
id_ = value
End Property
Public Property Set point(ByVal value As Collection)
Set point_ = value
End Property
Public Property Get ID() As Long
ID = id_
End Property
Public Property Get point() As Collection
Set point = point_
End Property
But here, when I try to run the code I get prompted with the following error:
Object module needs to implement 'X' for interface 'cPoint'
I think I know what it means, but I have no clue how to implement it. Is my approach even correct?
I'd highly appreciate any guidance in this manner.
VBA does not support inheritance. The only way to mimic inheritance is to implement your Point class and at the same time have a private instance of the Point class in your curve class. This is what your "Point" class would look like (I used "GeometryPoint" as the name of the class because Excel already has a "Point" class created):
Option Explicit
Private Type TState
ID As Long
X As Double
Y As Double
Z As Double
End Type
Private This As TState
Public Property Let ID(ByVal Value As Long)
This.ID = Value
End Property
Public Property Get ID() As Long
ID = This.ID
End Property
Public Property Let X(ByVal Value As Double)
This.X = Value
End Property
Public Property Get X() As Double
X = This.X
End Property
Public Property Let Y(ByVal Value As Double)
This.Y = Value
End Property
Public Property Get Y() As Double
Y = This.Y
End Property
Public Property Let Z(ByVal Value As Double)
This.Z = Value
End Property
Public Property Get Z() As Double
Z = This.Z
End Property
And this is what your "Curve" class would look like:
Option Explicit
Implements GeometryPoint
Private Type TState
Base As GeometryPoint
ID As Long
Points As Collection
X As Double
Y As Double
Z As Double
End Type
Private This As TState
Public Property Let GeometryPoint_ID(ByVal Value As Long)
This.Base.ID = Value
End Property
Public Property Get GeometryPoint_ID() As Long
GeometryPoint_ID = This.Base.ID
End Property
Public Property Let GeometryPoint_X(ByVal Value As Double)
This.Base.X = Value
End Property
Public Property Get GeometryPoint_X() As Double
GeometryPoint_X = This.Base.X
End Property
Public Property Let GeometryPoint_Y(ByVal Value As Double)
This.Base.Y = Value
End Property
Public Property Get GeometryPoint_Y() As Double
GeometryPoint_Y = This.Base.Y
End Property
Public Property Let GeometryPoint_Z(ByVal Value As Double)
This.Base.Z = Value
End Property
Public Property Get GeometryPoint_Z() As Double
GeometryPoint_Z = This.Base.Z
End Property
Public Property Set Points(ByVal Value As Collection)
Set This.Points = Value
End Property
Public Property Get Points() As Collection
Set Points = This.Points
End Property
Private Sub Class_Initialize()
Set This.Base = New GeometryPoint
End Sub
Private Sub Class_Terminate()
Set This.Base = Nothing
End Sub
In VBA, when you "Implement" a class you need to list all of the members (properties, methods) of that class. In your case you received an error because you didn't list the X,Y,Z properties of the cPoint class that you were implementing.
Is the "Curve" class supposed to have X,Y,Z properties as well? If not then you shouldn't implement the Point class. If the Curve class is just a class that stores a collection of Points then your Curve class should look like this:
**Note: This code was edited to include the "Class_Initialize" method which sets the "Points" member as a new collection once the Curve class is instantiated.
Option Explicit
Private Type TState
ID As Long
Points As Collection
End Type
Private This As TState
Public Property Let ID(ByVal Value As Long)
This.ID = Value
End Property
Public Property Get ID() As Long
ID = This.ID
End Property
Public Property Set Points(ByVal Value As Collection)
Set This.Points = Value
End Property
Public Property Get Points() As Collection
Set Points = This.Points
End Property
Private Sub Class_Initialize()
Set This.Points = New Collection
End Sub
Private Sub Class_Terminate()
Set This.Points = Nothing
End Sub
Finally, adding a new Point object to the "Points" member in the Curve class would look something like this:
Dim NewPoint As GeometryPoint
Dim NewCurve As Curve
Set NewPoint = New GeometryPoint
With NewPoint
.X = 1
.Y = 2
.Z = 3
End With
Set NewCurve = New Curve
With NewCurve.Points
.Add NewPoint
End With
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?
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
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.
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
I have a Devexpress Gridcontrol bound to a custom class.
The class looks like this:
Public Class AuditList
Public CasualtyList As List(Of CasualtyRecords)
Public MedsList As List(Of CasualtyRecords.Medications)
Public Property FilterString As CriteriaOperator
Public Sub New()
CasualtyList = New List(Of CasualtyRecords)
MedsList = New List(Of CasualtyRecords.Medications)
End Sub
Public Class CasualtyRecords
Private _primary As New PS
Public Property PrimarySurvey As PS
Get
Return _primary
End Get
Set(value As PS)
_primary = value
End Set
End Property
Public Sub New()
Vitals = New List(Of VitalRecords)
End Sub
Public Property Vitals As List(Of VitalRecords)
Public Property Meds As List(Of Medications)
ReadOnly Property MedCount As Integer
Get
Return Meds.Count
End Get
End Property
Property Id As Integer
Property ClinicalImpression As String
Property Disposal As String
Property Age As Integer
Property Gender As String
Class PS
Public Property Airway As Integer
Public Property Breathing As Integer
Public Property Circulation As Integer
Public Property Rate As Integer
End Class
Class Medications
Public Property MedName As String
End Class
End Class
End Class
This is an example of a filter type I am trying to create:
"[Gender] ='Male' AND [Medications].[MedName] = 'Paracetamol' AND [Age] >100"
Is this possible with the class constructed as shown, or perhaps do I need to implement some other interface?
I imagine that it would look something like this with LINQ
Dim b As New CasualtyRecords
b = a.CasualtyList.Where(Function(x) x.Meds.Any(Medications.Med = "Paracetamol") And x.Gender = "Male" And x.Age > 20)
Thanks
I was able to achieve the required results using this LINQ query
Dim newrecords = a.CasualtyList.Where(
Function(x) x.Meds.Any(
Function(b) b.MedName = "Paracetamol") _
And x.Gender = "Male" And x.Age > 20).ToList()
I am using the EntityFramework.SQLite library and for the life of me can not figure out how to combine two tables together into a temporary table for display purposes in xaml code.
Here's the code for my two tables I want to combine which is about all I am using right now besides a class for my temp table called CategoryList (this is part of the business/data logic dll library):
Partial Public Class CategoryList
Public Sub New()
Me.CategoryInfo = New CategoryReference
'Me.CategoryCode = New HashSet(Of CategoryCodes)
Me.CategoryCodes = New CategoryCodes
End Sub
Public Property MyId As Integer
<Key, ForeignKey("CodeID")>
<Required>
Public Property CodeID As Integer
<Key, ForeignKey("CategoryID")>
Public CategoryID As Integer
'Public Property CategoryCode As ICollection(Of CategoryCodes)
Public Property CategoryInfo As CategoryReference
' Public Property CategoryInfo As ICollection(Of CategoryReference)
Public Property CategoryCodes As CategoryCodes
End Class
<Table("CategoryCodes")>
Public Class CategoryCodes 'category shortnames/codes
<MaxLength(100)>
<Required>
Public Property CategoryCode As String
Get
Return _CategoryCode
End Get
Set(value As String)
_CategoryCode = value
End Set
End Property
Private _CategoryCode As String
'<NotNull>
' <PrimaryKey>
'<Unique(Name:="UQ__CategoryCodes__0000000000000081_CategoryCodes", Order:=0)>
<Key>
<Required>
Public Property CodeID As Integer
Get
Return CategoryCode
End Get
Set(value As Integer)
_CodeID = value
End Set
End Property
Private _CodeID As Integer
End Class
<Table("CategoryReference")>
Partial Public Class CategoryReference 'table design for category data
<MaxLength(100)>
Public Property CategoryName As String
Get
Return _CategoryName
End Get
Set(value As String)
_CategoryName = value
End Set
End Property
Private _CategoryName As String
<MaxLength(100)>
Public Property CategoryDescription As String
Get
Return _CategoryDescription
End Get
Set(value As String)
_CategoryDescription = value
End Set
End Property
Private _CategoryDescription As String
'<Unique(Name:="UQ__CatagoryReference__000000000000005F_CatagoryReference", Order:=0)>
<ForeignKey("CodeID")>
<Required>
Public Property CodeID As Integer
Get
Return _CodeID
End Get
Set(value As Integer)
_CodeID = value
End Set
End Property
Private _CodeID As Integer
'<Unique(Name:="UQ__CatagoryReference__000000000000005A_CatagoryReference", Order:=0)>
<Key>
<Required>
Public Property CategoryID As Integer
Get
Return _CategoryID
End Get
Set(value As Integer)
_CategoryID = value
End Set
End Property
Private _CategoryID As Integer
End Class
It may seem long but the tables are very simple and the get/set blocks make it look long (A vb.net editor can turn them into simple property's if she/he wishes). I may be using the CategoryList class wrong but here's where I use it in my xaml datasource in my main application code (I have business logic/data processing in a dll library):
Private Property ViewModel As List(Of UIELLUWP.DataAccess.CategoryList)
Dim categories As New UIELLUWP.DataAccess.SQLiteDb
ViewModel = categories.Categories.ToList
Errors received with current code:
I receive an error that Table "CategoryList" does not exist when I run the above code.
my solution I found out to this question was to add asnotracking because tracking was taking place.
How to pass a object that is initialized from a derived class to a method that has Interface as the parameter? Below is the example of what I'm trying. Is it possible? Please suggest any better way of doing.
Public Interface IFruit
Property Name As String
Property Color As String
End Interface
Public Class Fruit
Implements IFruit
Private _Name As String
Private _Color As String
Public Property Color As String Implements IFruit.Color
Get
Return _Color
End Get
Set(value As String)
_Color = value
End Set
End Property
Public Property Name As String Implements IFruit.Name
Get
Return _Name
End Get
Set(value As String)
_Name = value
End Set
End Property
End Class
Public Class FruitExtended
Inherits Fruit
Private _Taste As String
Public Property Taste() As String
Get
Return _Taste
End Get
Set(ByVal value As String)
_Taste = value
End Set
End Property
End Class
Public Class A
Public Sub ProcessFruit(F as IFruit)
'...
'Do something
End Sub
will the below code work? or how to achieve this in other ways?
Public Sub Test()
Dim F1 as new FruitExtended()
ProcessFruit(F1)
End sub
End Class
I didn't try your code, but - in general - interfaces are good because they define a behaviuor rather than a state (properties). So maybe you could rethink your design and ask yourself what the ProcessFruit is supposed to do with a IFruit.
Some languages even disallow to declare properties in interfaces, other than constants. Java is an example.