Is there a way to have a class collection of inherited types be initialized?
For example, here is my code:
Public Class CamryCar
Property Name As String = "Camry"
Property Color As String
End Class
Public Class RedCamry
Inherits CamryCar
Sub New()
MyBase.New()
Color = "Red"
End Sub
End Class
Public Class BlueCamry
Inherits CamryCar
Sub New()
MyBase.New()
Color = "Blue"
End Sub
End Class
What I'm doing today for a colllection is:
Public Class Camrys
Property Cars As New List(Of CamryCar) From {New RedCamry, New BlueCamry}
End Class
But this gives me an extra property of Cars.
I can also do this:
Public Class Camrys
Inherits List(Of CamryCar)
End Class
I prefer this one as I don't have an extra property to deal with. But I can find a way to initialize that that list with objects of RedCamry and BlueCamry.
Is it impossible or is there another way to do this?
Just another option. I'd probably pass the list in to the constructor. I also added an additional Sub New() that will initialize the collection via reflection.
Imports System.Reflection
Module Module1
Sub Main()
Dim camrys As New Camrys
For Each camry As CamryCar In camrys
Console.WriteLine(camry.Color)
Next
Console.ReadKey()
End Sub
End Module
Public Class Car
End Class
Public Class CamryCar
Inherits Car
Property Name As String = "Camry"
Property Color As String
End Class
Public Class RedCamry
Inherits CamryCar
Sub New()
MyBase.New()
Color = "Red"
End Sub
End Class
Public Class BlueCamry
Inherits CamryCar
Sub New()
MyBase.New()
Color = "Blue"
End Sub
End Class
Public Class Camrys
Inherits List(Of CamryCar)
Public Sub New(ByVal Camrys As List(Of CamryCar))
MyBase.New()
For Each Camry As CamryCar In Camrys
Add(Camry)
Next
End Sub
Public Sub New()
MyBase.New()
InitializeCamrys()
End Sub
Public Sub InitializeCamrys()
Dim asm As Assembly = Assembly.GetExecutingAssembly()
For Each t As Type In asm.GetTypes()
If GetType(CamryCar) Is t.BaseType Then
Dim camry As CamryCar = Activator.CreateInstance(t)
Add(camry)
End If
Next
End Sub
End Class
It seems like you're looking for a factory style function.
Module Factory
Public Function CreateCamrysList As List(of CamryCar)
Return New List(Of CamryCar) From {New RedCamry, New BlueCamry}
End Function
End Module
Now you can use the function CreateCamrysList wherever you need the list of CamryCar objects.
Note: Deriving from List(Of T) is in general a bad solution. If you do need to derive it's better to choose Collection(Of T).
You need to initialize it in a constructor:
Public Class Camrys
Inherits List(Of CamryCar)
Public Sub New()
MyBase.New()
Add(New RedCamry())
Add(New BlueCamry())
End Sub
End Class
Related
I want to call Dim objFkkiNinteiJokyoRpt As New A(objCsv) in class C. But class A Inherits Common. If now call contructor will An error occurred.Because type Object C.CsvGenerator diference type Object in common. I thnk now stop call to contructor common (or any other way) but i dont know how to do. Helf me please. Sorry because my english so bad
Public Class A Inherits Common
Public _objCsv As C.CsvGenerator
Friend Sub New(ByVal objCsv As C.CsvGenerator)
_objCsv = objCsvGenerator
End Sub
Public Sub New()
End Sub
End Sub
Public Sub New(ByVal objRSReportObj As Object)
MyBase.New(objRSReportObj)
InitializeReport()
End Sub
End Class
Public Class C
Private Function SelectCSV
Dim objCsv As New CsvGenerator("")
Dim objFkkiNinteiJokyoRpt As New A(objCsv)
End Function
Friend Class CsvGenerator
Inherits cmShare.cmObject
End Class
End Class
Public Class Common
Public Sub New()
MyBase.New()
End Sub
Public Sub New(ByVal objRSReport As Object)
MyBase.New(objRSReport)
End Sub
End Class
I am trying to retrieve a value from a overrides public variable, but surprisingly am getting the value from private property ?
Find below the code,
Project - Interfaces - Contains - IAnimal, IPoo
Project - ML - Contains - AnimalBase, Cat, Dog, Poo, RadioactivePoo
Project - ConsoleApplication - Contains - Modules
Public Interface IAnimal
ReadOnly Property Excrement() As List(Of Poo)
Sub Eat()
End Interface
Public Class Poo
End Class
Public Class RadioactivePoo
End Class
Public Class AnimalBase(Of T)
Implements IAnimal
Private _Excrement As List(Of Poo)
Public Overridable ReadOnly Property Excrement() As List(Of T)
Get
Return Nothing
End Get
End Property
Public Overridable Sub Eat() Implements IAnimal.Eat
If _Excrement Is Nothing Then
_Excrement = New List(Of Poo)
End If
_Excrement.Add(New Poo)
End Sub
Private ReadOnly Property Excrement1 As List(Of Poo) Implements IAnimal.Excrement
Get
Return Nothing
End Get
End Property
End Class
Public Class Dog
Inherits AnimalBase(Of Poo)
Private _Excrement As List(Of Poo)
Public Overrides ReadOnly Property Excrement() As List(Of Poo)
Get
Return _Excrement
End Get
End Property
Public Overrides Sub Eat()
If _Excrement Is Nothing Then
_Excrement = New List(Of Poo)
End If
_Excrement.Add(New Poo)
End Sub
End Class
Public Class Cat
Inherits AnimalBase(Of RadioactivePoo)
Private _Excrement As List(Of RadioactivePoo)
Public Overrides ReadOnly Property Excrement() As List(Of RadioactivePoo)
Get
Return _Excrement
End Get
End Property
Public Overrides Sub Eat()
If _Excrement Is Nothing Then
_Excrement = New List(Of RadioactivePoo)
End If
_Excrement.Add(New RadioactivePoo)
End Sub
End Class
Module Module1
Sub Main()
Dim dog As IAnimal = New Dog
dog.Eat()
'Dim dogPoo As Poo = dog.Excrement
Dim cat As IAnimal = New Cat()
cat.Eat()
'Dim catPoo As RadioactivePoo = cat.StronglyTypedExcrement()
Console.WriteLine(dog.Excrement.ToString)
Console.WriteLine(cat.Excrement.ToString)
Console.Read()
End Sub
End Module
I am trying to retrieve value from dog.Excrement / cat.Excrement, but surprisingly am getting it from dog.Excrement1 (which is private, but implemented by IAnimal Class).
How to get the value from Excrement ? , but when i tried to access, it returns nothing. see the pic, which lists the values, where you can see the public Excrement function has value, and private has nothing
I've got A base class Base and Sorter and Parser classes derived from it .
The same thing with BaseResult with derived SorterResult and ParserResult.
Base has a Result field of BaseResult type, BaseResult has a Log field.
The reason why I've used a Base class, is because both of Parser and Sorter must write a Log.
Here's my code:
Public MustInherit Class Base
Public Result As BaseResult
Event LogChanged()
Protected Sub AddLogLine(ByVal _logString As String)
If Not String.IsNullOrWhiteSpace(_logString) Then Result.Log.Add(_logString)
RaiseEvent LogChanged()
End Sub
End Class
Public Class Sorter
Inherits Base
Public Shadows Result As SorterResult
Sub New()
Result = New SorterResult With {.Log = New List(Of String)}
End Sub
Sub Go()
AddLogLine("Sorter started")
End Sub
End Class
Public Class Parser
Inherits Base
Public Shadows Result As ParserResult
Sub New()
Result = New ParserResult With {.Log = New List(Of String)}
End Sub
Sub Go()
AddLogLine("Sorter started")
End Sub
End Class
Public MustInherit Class BaseResult
Public Log As List(Of String)
End Class
Public Class SorterResult
Inherits BaseResult
'//SorterResult fields
End Class
Public Class ParserResult
Inherits BaseResult
'//ParsedResult fields
End Class
The issue here is that compiler sais(on pic below):
"variable 'Result' conflicts with variable 'Result' in the base class 'Base' and should be declared 'Shadows'." When I used Shadows keyword, warning disappeared, but I get a null reference exception on this line, because Result field is Nothing:
If Not String.IsNullOrWhiteSpace(_logString) Then Result.Log.Add(_logString)
I can't assign a value to a Result variable in Base class constructor, because It must be of type SorterResult in Sorter, and ParserResult in Parser. What is the regular pattern here? Sorry my bad english.
Use generics
Public MustInherit Class Base(Of TResult As BaseResult)
Public Result As TResult
Event LogChanged()
Protected Sub AddLogLine(ByVal _logString As String)
If Not String.IsNullOrEmpty(_logString) Then Result.Log.Add(_logString)
RaiseEvent LogChanged()
End Sub
Public MustOverride Sub Go()
End Class
Public Class Sorter
Inherits Base(Of SorterResult)
Sub New()
Result = New SorterResult With {.Log = New List(Of String)}
End Sub
Public Overrides Sub Go()
AddLogLine("Sorter started")
End Sub
End Class
Public Class Parser
Inherits Base(Of ParserResult)
Sub New()
Result = New ParserResult With {.Log = New List(Of String)}
End Sub
Public Overrides Sub Go()
AddLogLine("Sorter started")
End Sub
End Class
However, this is not a "beautiful" inheritance hierarchy. Inheritance should formulate relations like "a student is a person" where student derives from person. What do sorters and parsers have in common? Are they a Base? Are they loggers? Are they commands (as suggests the Go method)? Is inheritance required here? Wouldn’t it be more appropriate to use aggregation? I would declare a completely independent logger class and inject it into classes. This allows you to be more flexible, as it enables you to inject different types of loggers.
Public MustInherit Class Logger
Public Event LogChanged()
Public MustOverride Sub AddLogLine(ByVal message As String)
Protected Sub OnLogChanged()
RaiseEvent LogChanged()
End Sub
End Class
Public Class TextFileLogger
Inherits Logger
Public Overrides Sub AddLogLine(ByVal message As String)
If Not String.IsNullOrEmpty(message) Then
'TODO: Write message to log file
OnLogChanged()
End If
End Sub
End Class
You can inject it like this:
Public Class SomeConsumerClass
Private _logger As Logger
Sub New(ByVal logger As Logger)
_logger = logger
End Sub
Public Sub DoSomething()
_logger.AddLogLine("Did something!")
End Sub
End Class
Use like this:
Dim obj As New SomeConsumerClass(New TextFileLogger())
obj.DoSomething()
If you have another kind of logger (XmlFileLogger, StringListLogger, DatabaseLogger...) it is now easy to use it without having to change all the classes using it.
Maybe you should even have only one global logger:
Dim globalLogger As New TextFileLogger()
Dim sorter As New Sorter(globalLogger)
Dim parser As New Parser(globalLogger)
Say I have a class with several methods within it. I want to organize the methods into groupings that can be accessed without constructing a new object each time. The purpose is to group the methods of the class into logical buckets
For instance:
Dim myclass as MyCustomClass
myclass.Shipping.Get_List()
myclass.Production.Get_List()
What is the best way to do this? I tried nested classes, but VB.NET won't let me access the methods as shown above.
so this is how i would do what you want
this is not the best design of the world but it would work
I would suggest you to move the actual get_list and other kind of method / property into the specific class while keeping the common one in the parent class, which in this case is test
but then, I have no idea what your code look like so from that point on, it's your choice
Module Module1
Sub Main()
Dim test As New test
test.Production.Get_List()
test.Shipping.Get_List()
End Sub
End Module
Public Class Shipping
Private parent As test
Public Sub New(ByRef parent As test)
Me.parent = parent
End Sub
Public Function Get_List() As List(Of Integer)
Return parent.GetShipping_List
End Function
End Class
Public Class Production
Private parent As test
Public Sub New(ByRef parent As test)
Me.parent = parent
End Sub
Public Function Get_List() As List(Of Integer)
Return parent.GetProduction_List
End Function
End Class
Public Class test
Public Property Production As Production
Public Property Shipping As Shipping
Public Function GetShipping_List() As List(Of Integer)
Return Nothing
End Function
Public Function GetProduction_List() As List(Of Integer)
Return Nothing
End Function
Public Sub New()
Production = New Production(Me)
Shipping = New Shipping(Me)
End Sub
End Class
With caution that you more than likely should re-evaluate your architecture, you could implement your pattern like this:
Public Class MyCustomClass
Private _shippingList As List(Of String)
Private _productionList As List(Of String)
Public Production As ProductionClass
Public Shipping As ShippingClass
Public Sub New()
Production = New ProductionClass(Me)
Shipping = New ShippingClass(Me)
End Sub
Public Class ShippingClass
Private _owner As MyCustomClass
Public Sub New(owner As MyCustomClass)
_owner = owner
End Sub
Public Function Get_List()
Return _owner._productionList
End Function
End Class
Public Class ProductionClass
Private _owner As MyCustomClass
Public Sub New(owner As MyCustomClass)
_owner = owner
End Sub
Public Function Get_List()
Return _owner._productionList
End Function
End Class
End Class
However, if your true intent is simply organizing the methods in a more accessible and logical manner, I would suggest considering:
Public Class MyCustomClass
Public Sub ShippingListGet()
End Sub
Public Sub ShippingListAddTo()
End Sub
Public Sub ShippingThatDO()
End Sub
Public Sub ShippingThisDo()
End Sub
Public Sub ProductionListGet()
End Sub
Public Sub ProductionListAddTo()
End Sub
Public Sub ProductionThisDo()
End Sub
Public Sub ProductionThatDo()
End Sub
End Class
Keep in mind, some people consider that difficult to read. I personally prefer organization along those lines so when the methods are sorted alphabetically they group logically.
I have found the solution I was looking for using interfaces
Public Interface ICompany
Function Company_List() As DataTable
End Interface
Public Class MainClass
Public Company As ICompany = New CompanyClass
Public Sub New()
MyBase.New()
End Sub
Private Class CompanyClass
Public Sub New()
MyBase.New()
End Sub
Public Function Company_List() As DataTable
My code....
End Function
End Class
End Class
I have these two classes class FootballAdmin makes use of the import Football from the projects references, what i need to do is in class MainForm is for the updateView method to access the list held by FootballAdmin and display it in the teamSheetListBox, i am unsure how access the list as indicated by ?????
Imports Football
Public Class FootballAdmin
Private fTeam As List(Of FootballTeams)
Public Sub New()
fTeam = New List(Of FootballTeams)
End Sub
Public ReadOnly Property Teams() As List(Of FootballTeams)
Get
Return fTeams
End Get
End Property
End Class
Public Class MainForm
Private fFootballAdmin As FootballAdmin
Public Sub New()
InitializeComponent()
fFootballAdmin = New FootballAdmin
updateView()
End Sub
Private sub updateView()
For each team As String In ????????
teamSheetListBox.Items.Add(team)
Next
End Sub
End Class
Help please!
The big hint I am going to give you is that team in your loop:
For each team As String In ????????
teamSheetListBox.Items.Add(team)
Next
Isn't going to be a String. It will be the same type: FootballTeam as in your FootballAdmin Class. Consider what you have access to in your MainForm that can get you to those types.