Overloaded Constructor in Abstract Class in vb.NET - vb.net

I have an abstract class in vb.net with two subclasses. In the abstract class I have a constuctor that looks like this:
Public Sub New(arg1 as String, arg2 as String)
Me.arg1 = arg1
Me.arg2 = arg2
End Sub
I would like to create a second constructor that doesn't take any arguments and just initializes the args to default values. It would look like this:
Public Sub New()
Me.arg1 = "123"
Me.arg2 = "456"
End Sub
When I attempt to create a new subclass using the second constructor the compiler complains that I'm missing two args to the constructor.... Is there a reason I can't overload the constructor in the abstract class?
Thanks

There's no "abstract" in VB. If you mean abstract in the c# sense (MustInherit in VB parlance), then you need to define both constructors in your subclasses, as constructors are not inherited.
Example:
Public MustInherit Class SuperClass
Public Property ValueOne As String = String.Empty
Public Property ValueTwo As String = String.Empty
Public Sub New()
Me.New("123", "456")
End Sub
Public Sub New(ByVal tValueOne As String, ByVal tValueTwo As String)
Me.ValueOne = tValueOne
Me.ValueTwo = tValueTwo
End Sub
End Class
Public Class SubClass
Inherits SuperClass
Public Sub New()
MyBase.New()
End Sub
Public Sub New(ByVal tValueOne As String, ByVal tValueTwo As String)
MyBase.New(tValueOne, tValueTwo)
End Sub
End Class

If your second constructor is in the sub class, it must call the constructor in the base class.
Public Sub New()
MyBase.New("123", "456")
End Sub

Related

Implement same logic for diffrent objects as T

I suppose to use T but i am not sure how do it in proper way.
Let's consider following example.
Base class:
Public Class HtmlBase
Implements IGetInformation
Public Overridable Function IsExist() As Boolean Implements IGetInformation.IsExist
Throw New NotImplementedException()
End Function
Public Overridable Function GetIdByName(pName As String) As Integer Implements IGetInformation.GetIdByName
Throw New NotImplementedException()
End Function
End Class
Example classes which inherit from base class:
Public Class HtmlSubSection
Inherits HtmlBase
'--sometimes i have to overload to add additioinal parameter
Public Overloads Function isExist(subsection As String) As Boolean
Dim dlsubkategorie As New DataLayer.DALSubSection
Return dlsubkategorie.CheckIfSubSectionExist(subsection)
End Function
Public Overrides Function GetIdByName(subsectionName As String) As Integer
Dim dlget As New DataLayer.DALSubSection
Return dlget.GetSubSectionIdByName(subsectionName)
End Function
End Class
Public Class HtmlSection
Inherits HtmlBase
'sometime i have to overload to add additioinal parameter
Public Overloads Function IsExist(section As String) As Boolean
Dim dlsubkategorie As New DataLayer.DALSection
Return dlsubkategorie.CheckIfSectionExist(section)
End Function
Public Overrides Function GetIdByName(Name As String) As Integer
Dim dlsubkategorie As New DataLayer.DALSection
Return dlsubkategorie.GetSectionIdByName(Name)
End Function
End Class
As could be seen above two classes which inherits from base within their methods has same logic (sometimes i have to use additional parameter therefore overloads there, but are using diffrent DAL class to call. I would like to implement this logic in base class and for each just point to specific DAL. How to do that to not everytime in those classes write e.g:
Dim dlsubkategorie As New DataLayer.<DALSection>
Return dlsubkategorie.GetSectionIdByName(Name)
EDIT:
Htmlbase constructor's:
Sub New()
End Sub
Sub New(pId As Integer)
_Id = pId
End Sub
HtmlSubSection's constructors:
Sub New()
MyBase.New()
AvailableSentences = New List(Of HtmlSubSection_Sentence)
SelectedSentences = New List(Of HtmlSubSection_Sentence)
End Sub
Sub New(pId As Integer)
MyBase.New(pId)
End Sub
Sub New(pName As String)
_Name = pName
End Sub
Sub New(pId As Integer, pName As String)
MyBase.New(pId)
_Name = pName
End Sub
HtmlSection's constructors:
Sub New()
MyBase.New()
End Sub
Sub New(pId As Integer)
MyBase.New(pId)
End Sub
Sub New(pId As Integer, pName As String, pPosition As Integer)
MyBase.New(pId)
_Name = pName
_Position = pPosition
End Sub
Sub New(pName As String)
_Name = pName
End Sub
Sub New(pName As String, pPosition As Integer)
_Name = pName
_Position = pPosition
End Sub
You don´t need generic types here. Just use Interfaces, Sub Classing and Polymorphism correctly.
New Interface IDAL which is implemented by DAL classes to get rid of different method names which take same parameters and do the same:
Public Interface IDAL
Function CheckIfSectionExist(section As string) As Boolean
Function GetSectionIdByName(section As string) As Integer
End Interface
Public Class DALSection
Implements IDAL
Public Function CheckIfSectionExist(section As string) As Boolean Implements IDAL.CheckIfSectionExist
...
End Function
Public Function GetSectionIdByName(section As String) As Integer Implements IDAL.GetSectionIdByName
...
End Function
End Class
Public Class DALSubSection
Implements IDAL
Public Function CheckIfSubSectionExist(subSection As string) As Boolean Implements IDAL.CheckIfSectionExist
...
End Function
Public Function GetSubSectionIdByName(subSection As String) As Integer Implements IDAL.GetSectionIdByName
...
End Function
End Class
Base class changed to abstract and the constructor now takes IDAL parameter. Function can now be executed polymorphic. Added a isExists(string) function to avoid overloading:
Public MustInherit Class HtmlBase
Implements IGetInformation
Public Property DAL as DataLayer.IDAL
Protected Sub New(dal as DataLayer.IDAL)
Me.DAL = dal
End Sub
Public Overridable Function isExist() As Boolean Implements IGetInformation.isExist
Return True
End Function
Public Overridable Function isExist(section As String) As Boolean
Return DAL.CheckIfSectionExist(Section)
End Function
Public Overridable Function GetIdByName(pName As String) As Integer Implements IGetInformation.GetIdByName
Return DAL.GetSectionIdByName(pName)
End Function
End Class
Client classes only need to give correct DAL to base class:
Public Class HtmlSubSection
Inherits HtmlBase
Public Sub New()
MyBase.New(New DataLayer.DALSubSection)
End Sub
End Class
Public Class HtmlSection
Inherits HtmlBase
Public Sub New()
MyBase.New(New DataLayer.DALSection)
End Sub
End Class
Basically it would be ideal if IGetInformation had a isExist method with an optional string parameter. This would save one unneccessary method in HtmlBase.

VB.NET Inheritance issue

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)

how to access class from inherited class

I have two classes:
class class2
inherits class1
public sub modify()
'modify property of class1
end sub
end class
How can I modify class1 in a sub in class2?
You just call it. Example:
Public Class class1
Private _Value As String = String.Empty
Property Value() As String
Get
Return _Value
End Get
Set(ByVal value As String)
_Value = value
End Set
End Property
End Class
Public Class class2
Inherits class1
Public Sub modify()
Value = "modified"
End Sub
End Class
And to show it works:
Dim c2 As New class2
c2.modify()
MessageBox.Show(c2.Value)
You are asking about properties, note that only protected and public properties are visible to inherited classes.
You need the MyBase keyword when you are overriding an existing function in the parent class. Other protected or public properties or functions can be accessed regulary without any special keyword.
One tip I wanted to add to the above comments regarding accessing base class info is where you have a base class without a default contructor or want to use a specific constructor This is a good opportunity to use Mybase. You have to call the constructor before any additional actions take place in this scenario.
Public Class MyClass
Inherits baseClass
Public Sub New()
mybase.new("Oranges")
End Sub
End Class
Public Class baseClass
Private _someVariable as String
Public Sub New(byval passedString as string)
_someVariable = passedString
End Sub
End Class

How to implement class constructor in Visual Basic?

I just would like to know how to implement class constructor in this language.
Not sure what you mean with "class constructor" but I'd assume you mean one of the ones below.
Instance constructor:
Public Sub New()
End Sub
Shared constructor:
Shared Sub New()
End Sub
Suppose your class is called MyStudent. Here's how you define your class constructor:
Public Class MyStudent
Public StudentId As Integer
'Here's the class constructor:
Public Sub New(newStudentId As Integer)
StudentId = newStudentId
End Sub
End Class
Here's how you call it:
Dim student As New MyStudent(studentId)
Of course, your class constructor can contain as many or as few arguments as you need--even none, in which case you leave the parentheses empty. You can also have several constructors for the same class, all with different combinations of arguments. These are known as different "signatures" for your class constructor.
If you mean VB 6, that would be Private Sub Class_Initialize().
http://msdn.microsoft.com/en-us/library/55yzhfb2(VS.80).aspx
If you mean VB.NET it is Public Sub New() or Shared Sub New().
A class with a field:
Public Class MyStudent
Public StudentId As Integer
The constructor:
Public Sub New(newStudentId As Integer)
StudentId = newStudentId
End Sub
End Class

Similar classes with different signatures

I have two classes:
Public Class Subscribing
Private _subscribingObjects As IList(Of String)
Public Sub Add(ByVal obj As SubscribeObject)
'...code...'
End Sub
Public Sub Remove(ByVal index As Integer)
'...code...'
End Sub
End Class
Public Class Providing
Private _providingObjects As IList(Of String)
Public Sub Add(ByVal obj As ProvideObject)
'...code...'
End Sub
Public Sub Remove(ByVal index As Integer)
'...code...'
End Sub
End Class
Is there a more elegant way to add do this? One class would suffice, but since the Add methods have different arguments, then one really wouldn't work.
Any help would be appreciated.
this?
Public Class SubscribingProviding(Of t)
Private _subscribingObjects As IList(Of String)
Public Sub Add(ByVal obj As t)
'...code...'
End Sub
Public Sub Remove(ByVal index As Integer)
'...code...'
End Sub
End Class
Your add functions should be fine. As long as you have different variable types being passed in you can have the function names be the same. Your remove Subs will not be allowed in the same class because it is using the same parameter Integer.
Eh.. probably not. They are different enough that you cant even Interface them.
I personally wouldn't mix the two responsibilities (of subscribing and providing) in one class. The classes themselves can easily be simplified by just inheriting from List(Of T)
Public Class Subscribing
Inherits List(Of SubscribeObject)
End Class
Public Class Providing
Inherits List(Of ProvideObject)
End Class
If you really want to get down to one class and make sure that it can only accept SubscribeObject and ProvideObject respectively, implement a common interface in both SubscribeObject and ProvideObject. Then create a generic class that accepts the interface:
' Common interface '
Public Interface ISubscribeProvideObject
End Interface
' SubscribeObject and ProvideObject both implementing the common interface '
Public Class SubscribeObject
Implements ISubscribeProvideObject
'...'
End Class
Public Class ProvideObject
Implements ISubscribeProvideObject
'...'
End Class
' Generic class accepting both types '
Public Class SubscribingProviding(Of T As ISubscribeProvideObject)
Inherits List(Of T)
'... Add() and Remove() methods only needed if custom logic applies ...'
End Class