Why in VB.NET is not possible te declare a NotOverridable method? - vb.net

I'm trying to avoid that sub-classes of my class can override my method.
If I try to do so by using the NotOverridable keyword:
Public Class Class1
Protected NotOverridable Sub DoSomething()
End Sub
End Class
I get this error:
'NotOverridable' cannot be specified on methods that do not override another method

Let's say that you have this class:
Public Class GrandParent
Protected Sub Method1()
End Sub
Protected Overridable Sub Method2()
End Sub
End Class
and then you have this class:
Public Class Parent
Inherits GrandParent
Protected Sub Method1()
End Sub
Protected Overrides Sub Method2()
End Sub
End Class
Parent.Method2 is overriding GrandParent.Method2, just as indicated. On the other hand, Parent.Method1 is NOT overriding GrandParent.Method1. That code generates the following warning:
sub 'Method1' shadows an overloadable member declared in the base
class 'GrandParent'. If you want to overload the base method, this
method must be declared 'Overloads'.
If you change the code to the following:
Public Class Parent
Inherits GrandParent
Protected Overrides Sub Method1()
End Sub
Protected Overrides Sub Method2()
End Sub
End Class
then you get the following error:
'Protected Overrides Sub Method1()' cannot override 'Protected Sub
Method1()' because it is not declared 'Overridable'.
Shadowing is different to overloading in that shadowing honours the type of the reference while overriding honours the type of the object. That means that, if you you have a Parent object assigned to a GrandParent variable, calling Method1 will invoke GrandParent.Method1 based on the type of the reference and calling Method2 will invoke Parent.Method2 based on the type of the object. Overriding implements polymorphism where shadowing does not. The first implementation of Parent is equivalent to this:
Public Class Parent
Inherits GrandParent
Protected Shadows Sub Method1()
End Sub
Protected Overrides Sub Method2()
End Sub
End Class
If you were to then add this class:
Public Class Child
Inherits Parent
Protected Overrides Sub Method2()
End Sub
End Class
it would work as expected. If you changed the Parent class to this:
Public Class Parent
Inherits GrandParent
Protected Shadows Sub Method1()
End Sub
Protected NotOverridable Overrides Sub Method2()
End Sub
End Class
then that `Child implementation would generate this error:
'Protected Overrides Sub Method2()' cannot override 'Protected
NotOverridable Overrides Sub Method2()' because it is declared
'NotOverridable'.
That is the only reason to use the NotOverridable keyword, i.e. to prevent derived classes overriding your own overridden implementation of an inherited member.

Related

How to cast object of type 'especific' to type 'FileHelpers.Events.INotifyRead in Multirecording

I'm trying to centralize all formatting and conversion rule in a single class especific. Using the interface INotifyRead(Of T As Class). When I implement the methods BeforeRead/AfterRead throws an exception: Unable to cast object of type 'Especific' to type 'FileHelpers.Events.INotifyRead`1[System.Object]'.
Below my code.
Using engine As New MultiRecordEngine(New RecordTypeSelector(AddressOf CifraRecordTypeSelector),
GetType(RemessaRegistroCliente),
GetType(RemessaRegistroContrato))
Dim records = engine.ReadFile(_camArquivo)
End Using
Public NotInheritable Class RemessaRegistroCliente
Implements INotifyRead(Of RemessaRegistroCliente)
Public Sub AfterRead(e As AfterReadEventArgs(Of RemessaRegistroCliente)) Implements INotifyRead(Of RemessaRegistroCliente).AfterRead
End Sub
Public Sub BeforeRead(e As BeforeReadEventArgs(Of RemessaRegistroCliente)) Implements INotifyRead(Of RemessaRegistroCliente).BeforeRead
End Sub
End Class
Public NotInheritable Class RemessaRegistroContrato
Implements INotifyRead(Of RemessaRegistroContrato)
Public Sub AfterRead(e As AfterReadEventArgs(Of RemessaRegistroContrato)) Implements INotifyRead(Of RemessaRegistroContrato).AfterRead
End Sub
Public Sub BeforeRead(e As BeforeReadEventArgs(Of RemessaRegistroContrato)) Implements INotifyRead(Of RemessaRegistroContrato).BeforeRead
End Sub
End Class
Since MultiRecordEngine has no generic version, you cannot implement the generic INotifyRead(Of T) to handle events. Instead, assign delegates to the engine.
Sub Main()
Using engine As New MultiRecordEngine(New RecordTypeSelector(AddressOf CifraRecordTypeSelector),
GetType(RemessaRegistroCliente),
GetType(RemessaRegistroContrato))
AddHandler engine.BeforeReadRecord, AddressOf BeforeReadRecordHandler
End Using
End Sub
Private Sub BeforeReadRecordHandler(ByVal engine As EngineBase, ByVal e As BeforeReadEventArgs(Of Object))
End Sub
You'll also need to modify your classes to remove the generic interfaces:
Public NotInheritable Class RemessaRegistroCliente
'your fields
End Class
Public NotInheritable Class RemessaRegistroContrato
'your fields
End Class

Inner class Factory Method

I have tried to implement the Factory method with a trick, but for some reason is not working:
Public Class MetamodelElement
Public Class MetamodelElementFactoryBase
End Class
Private Sub New()
End Sub
End Class
Public Class MetamodelElementFactory : Inherits MetamodelElement.MetamodelElementFactoryBase
Function CreateMetamodelElement() As MetamodelElement
Return New MetamodelElement()
End Function
End Class
It says that the class does not have access to the private method (constructor).
I have followed an example from C# in this post:
Hidden Features of C#?
The compiler complains that you are trying to use the Private constructor from outside of the class. That is not allowed. So either make it Public or don't call it.
Public Class MetamodelElement
Public Class MetamodelElementFactoryBase
End Class
Public Sub New() ' <---- HERE!!! Now it works because it's public
End Sub
End Class
Public Class MetamodelElementFactory
Inherits MetamodelElement.MetamodelElementFactoryBase
Function CreateMetamodelElement() As MetamodelElement
Return New MetamodelElement() ' <--- HERE was the error
End Function
End Class
You can access private class members only from inside of the class.
MSDN: Access Levels
According to the C# code that you've linked you have to move the constructor into the class that you are inheriting from. Then you can also use Protected:
Public Class MetamodelElement
Public Class MetamodelElementFactoryBase
Protected Sub New()
End Sub
End Class
End Class

Defer (lazy creation) or suppress creation of Unity Call Handler Attributes until the decorated method is actually called

I am trying to use Interception Call Handler and Handler Attributes on my interfaces (or implementation). Lets say my Interface has two methods DoSomething() and DoSomethingElse(), and I only have the interceptor for DoSomethingElse(); when I resolve my main interface the constructor for the Call Handler get called even if I never invoke DoSomethingElse().
I tried this by resolving to Lazy(of IMainInterface) but the moment I call the function DoSomething() the Call Handler is still created unnecessarily. Is there a way to prevent this from happening either by code or configuration. Here is my sample implementation
Handler Attribute and Call Handler
<AttributeUsage(AttributeTargets.Method)>
Public Class NormalSampleAttribute
Inherits HandlerAttribute
Public Sub New()
Console.WriteLine("Constructor of Normal Sample Attribute")
End Sub
Public Overrides Function CreateHandler(container As Microsoft.Practices.Unity.IUnityContainer) As Microsoft.Practices.Unity.InterceptionExtension.ICallHandler
Console.WriteLine("Create Handler")
Return New SampleCallHandler
End Function
End Class
Public Class SampleCallHandler
Implements ICallHandler
Public Sub New()
Console.WriteLine("Constructor of Sample Call handler")
End Sub
Public Function Invoke(input As IMethodInvocation, getNext As GetNextHandlerDelegate) As IMethodReturn Implements ICallHandler.Invoke
Console.WriteLine("Invoke of Sample Call handler - " & input.MethodBase.Name)
Return getNext.Invoke(input, getNext)
End Function
Public Property Order As Integer Implements ICallHandler.Order
End Class
Interface and implementation
Public Interface IMainInterface
Sub DoSomething()
<NormalSample()>
Sub DoSomethingElse()
End Interface
Public Class MainClass
Implements IMainInterface
Public Sub New()
Console.WriteLine("main class - Constructor")
End Sub
Public Sub DoSomething() Implements IMainInterface.DoSomething
Console.WriteLine("main class do something...")
End Sub
Public Sub DoSomethingElse() Implements IMainInterface.DoSomethingElse
Console.WriteLine("main class do something else...")
End Sub
End Class
Main module to register and execute the method
Module Module1
Public container As IUnityContainer
Sub Main()
container = New UnityContainer
DoRegistrations()
Console.WriteLine("Before lazy Resolve")
Dim lmc As Lazy(Of IMainInterface) = container.Resolve(Of Lazy(Of IMainInterface))()
Console.WriteLine("Before making lazy function call")
lmc.Value.DoSomething()
Console.ReadLine()
End Sub
Sub DoRegistrations()
container.AddNewExtension(Of InterceptionExtension.Interception)()
container.RegisterType(Of IMainInterface, MainClass)()
container.Configure(Of Interception).SetDefaultInterceptorFor(Of IMainInterface)(New InterfaceInterceptor)
End Sub
End Module
It produces the following output:
Before lazy Resolve
Before making lazy function call
main class - Constructor
Constructor of Normal Sample Attribute
Create Handler
Constructor of Sample Call handler
main class do something...
Even though DoSomethingElse() is never called the cost of the handler creation is being added on all flows. Is there any way to avoid this? Any help is appreciated.
Thanks in advance!
SV

Override object definition in a child and use it in parent

I have an object (called Ticker) that is defined in a parent class (CoreEngine), which I am trying to over-ride with a different object definition (but keep same name to use in CoreEngine) in one of the parent class's children. I think I'm supposed to use the 'Shadows' definition but I seem to be setting the object to null.
The ticker object is one that I want to use with methods defined in the parent class, but I want to change its type when defining a child of CoreEngine to use a different ticker object definition.
Public Class CoreEngine
Public WithEvents Ticker As TickerClass
Public Sub New()
End Sub
Public Overridable Sub Activate()
Ticker = New TickerClass()
End Sub
''call methods that use Ticker
End Class
And in the child class:
Public Class ChildEngineClass
Inherits CoreEngine
Public Shadows WithEvents Ticker As BacktestTickerClass ' <<-- this class inherit the TickerClass too
Public Sub New()
End Sub
Public Overrides Sub Activate()
Ticker = New BacktestTickerClass()
End Sub
End Class
Overriding the Activate() method seems to work but when 'Ticker' is then referenced in the parent object's method it has a null reference. So my question is what am I doing wrong? how can i override the Ticker object in defined in the parent to reference a different object (which is also a child of the Ticker class) and still be able to use it in the parent object CoreEngine?
In short, you cannot change the type of the field in the type class and expect the parent to know about it. Parent doesn't know anything about its children and doesn't know that you changed the type.
Since BacktestTickerClass inherits from TickerClass, what you can do is not change the definition of Ticker but still override Activate and instantiate it as the child class:
Public Class ChildEngineClass
Inherits CoreEngine
Public Sub New()
End Sub
Public Overrides Sub Activate()
Ticker = New BacktestTickerClass()
End Sub
End Class
Obviously, this way you can only use methods that are available to TickerClass in your parent class. If you need to use anything that is available only in BacktestTickerClass, you have to override a method from parent in ChildEngineClass.
Use inheritance on the tickers
Public Class BaseTicker
'...
End Class
Public Class DerivedTicker1
Inherits BaseTicker
'...
End Class
Public Class DerivedTicker2
Inherits BaseTicker
'...
End Class
Now you can define the ticker using the base ticker and assign it derived tickers
Public Class CoreEngine
Public WithEvents Ticker As BaseTicker
Public Sub New()
Ticker = New DerivedTicker1() 'Or possibly New BaseTicker()
End Sub
'...
End Class
Public Class ChildEngineClass
Inherits CoreEngine
'Do not redefine Ticker here.
'Ticker is automatically inherited from the base class.
Public Sub New()
Ticker = New DerivedTicker2()
End Sub
End Class

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