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)