I have a base class and derived class, the base class has two methods which are overridden in the derived class. Let's take the following scenario:
My base class
public class BaseClass
public Overridable function method1()
method2()
End Function
public Overridable function method2()
' Empty !!!
End Function
End class
My Derived class
public class DerivedClass
public Overrides function method1()
MyBase.method1()
End Function
public Overrides function method2()
' Some code !!
End Function
End class
Now I have created an instance of the derived class and call method1().
Dim obj as new DerivedClass()
obj.method1()
method1() in the derived calls method1() in the base, which calls method2 in the base. the strange thing to me that method2 in base, which is empty, called the method2 in the derived! ..
Can any one explain to me what is happening and how calling methods with inheritance done? and what concept was applied with this hierarchy ?
method1() in the derived calls method1() in the base, which calls method2 in the base.
This is where you are wrong.
Since method2 is overridable, it is a "virtual method". Thus, all calls to method2 call the overridden version. This includes the method2 invocation in method1 of the base class:
Public Class BaseClass
Public Overridable function method1()
method2() ' <-- If method2 has been overridden, the overridden
' version is called here.
End Function
...
End Class
Overridable methods in VB, like virtual methods in C#, are not called directly but typically employ what is called a vtable which contains pointers to methods. In this way when you have an instance of type BaseClass the vtable will point to the BaseClass version of the overridable method. When you have an instance of DerivedClass a pointer to its version of the method overwrites what was in the vtable and so when the method is invoked it will call the derived class version. For more information on vtables see this question
Related
Let's say I got this interface:
Public Interface IGsm
Function Run(filePath As String) As Boolean
End Interface
Now I want all child classes to use IGsm interface, therefore I decided to implement it by abstract class (hope it's good approach):
Public Class MustInherit GsmBase
Implements IGsm
Public Function Run(filePath As String) As Boolean Implements IGsm.Run
Throw New NotImplementedException()
End Function
End Class
First question:
What if I put Overridable to my function does it mean that I can define some implementation here in base class same for all derived classes and also ovveride rest implementation in derived classes? Is that correct approach?
Public Overridable Function Run(filePath As String) As Boolean Implements IGsm.Run
'Some shared code for all child classes
'......
End Function
so derived classes could do:
Public Ovverides Function Run(filePath As String) As Boolean Implements IGsm.Run
MyBase.Run
'add additional code for this specific child class...
End Function
Is that all correct what I just wrote?
Second question: If I do not mark Run as Overridable in base class. When inheriting from base class to my derived classes does it mean that my derived classes will just have to use the current implementation of that Run method from base class?
Third question: Why I cannot mark Run in base class as MustOverides?
Functions, Subs and properties and also Interface implementations are inherited in deriving classes, no matter whether the members are Overridable / Overridden or not.
Overridable means that a deriving class can just do nothing, if it is happy with the base implementation. A call to a Function will automatically call the base function. But it can override it, if another implementation is desired. You can then decide to call the base implementation or not, depending whether you want to add functionality or want to replace it completely.
Apply MustInherit to the class. This enables you to apply MustOverride to members. (This is a bit more complicated than in C#, where you can apply the same keyword abstract twice.)
Public MustInherit Class GsmBase
Implements IGsm
Public MustOverride Function Run(filePath As String) As Boolean Implements IGsm.Run
End Class
Note that you can combine different approaches. You could have several abstract base classes implementing the interface and also classes implementing the interface directly
Interface I
MustInherit Class BaseA Implements I
MustInherit Class BaseB Implements I
Class A1 Inherits BaseA
Class A2 Inherits BaseA
Class A2_1 Inherits A2
Class B1 Inherits BaseB
Class B2 Inherits BaseB
Class C Implements I
Class D Inherits C
Class E Inherits D
All objects of type A1, A2, A2_1,B1, B2, C, D and E are assigment compatible to I.
You didn't create an abstract class in your sample, it would look like this.
Public Interface IGsm
Function Run(filePath As String) As Boolean
End Interface
Public MustInherit Class GsmBase
Implements IGsm
Public MustOverride Function Run(filePath As String) As Boolean Implements IGsm.Run
End Class
Public Class Gsm
Inherits GsmBase
Public Overrides Function Run(filePath As String) As Boolean
Return False
End Function
End Class
Then you can use is as
Dim test As IGsm = New Gsm
test.Run("test") ' This will call Gsm.Run
or
Dim test As GsmBase = New Gsm
test.Run("test") ' This will call Gsm.Run
MustInherit is for class, not method. For method you would use MustOverride.
I need all my TableAdapters to implement a custom interface. The problem is that some of the members defined by the interface reside in the DataSet's designer file, which I don't want to (and shouldn't) alter, as that code will be regenerated automatically. I can't relocate those members to my code file either for the same reason. What's my way out of it?
When you implement an interface, the members you declare do not have to have the same names as the members of the interface and they don't have to be public. Let's say that you have this designer-generated class:
Partial Public Class SomeClass
Public Sub FirstMethod()
Console.WriteLine("FirstMethod")
End Sub
Public Sub SecondMethod()
Console.WriteLine("SecondMethod")
End Sub
End Class
and you want it to implement this interface:
Public Interface ISomeInterface
Sub FirstMethod()
Sub ThirdMethod()
End Interface
Notice that the interface has a method named FirstMethod but SomeClass already has a method named FirstMethod. You can add your own partial class to implement the interface like this:
Partial Public Class SomeClass
Implements ISomeInterface
Private Sub FirstMethodInternal() Implements ISomeInterface.FirstMethod
Me.FirstMethod()
End Sub
Public Sub ThirdMethod() Implements ISomeInterface.ThirdMethod
Console.WriteLine("ThirdMethod")
End Sub
End Class
The method that implements ISomeInterface.FirstMethod is not named FirstMethod so it doesn't clash with the existing method with that name and it is also Private so it cannot be accessed from outside using a reference of type SomeClass. Using a reference of type ISomeInterface is another matter though. If you use code like this:
Dim sc As ISomeInterface = New SomeClass
sc.FirstMethod()
sc.ThirdMethod()
you'll find that the FirstMethodInternal method of your SomeClass object gets invoked and, in turn, invokes the FirstMethod method of the same object. Try running that code and placing breakpoints on the FirstMethod and FirstMethodInternal methods to prove it to yourself.
Disclaimer: I am fairly new to working with generics so I am not entirely sure if what I am trying to do even makes sense or is possible.
I have a bunch of user controls in a project. All of these user controls share a similar property so I want to move it into a base class. The only difference is the return type of the property.
I have three classes interacting in this scenario. The first class is a base type, which inherits from CompositeControl and will be inherited by other classes in my project:
Friend Class MyBaseClass(Of T As {New})
Inherits CompositeControl
Private _someProperty As T = Nothing
Protected ReadOnly Property SomeProperty As T
Get
// dumbed down for the sake of example
If _someProperty Is Nothing Then
_someProperty = New T()
End If
Return _someProperty
End Get
End Property
End Class
Then I have this control class, which inherits from MyBaseClass:
Public Class MyControlClass
Inherits MyBaseClass(Of MyReturnTypeClass)
// snip...
End Class
And finally MyReturnTypeClass which is what the base's SomeProperty should return:
Friend Class MyReturnTypeClass
Public Property AutoProperty1 As Boolean = False
Public Property AutoProperty2 As String = String.Empty
// etc
End Class
When I attempt to build the project, I get this error from MyControlClass:
Inconsistent accessibility: type argument 'MyReturnTypeClass' is less accessible than Class 'MyControlClass'.
I need MyControlClass to be Public so it can be consumed by other projects, and I also want the MyBaseClass and MyReturnTypeClass to be Friend so they cannot be seen/used by consumers. Am I just missing some special keyword somewhere or is this not possible?
You cannot inherit from a base class that is less accessible than the derived class. So for instance, this won't work:
Friend Class MyBase
End Class
Public Class MyDerived
Inherits MyBase ' Won't compile because MyBase is less accessible
End Class
Therefore, since in your example, MyBaseClass(T) has is a friend type, but you are trying to inherit from it into a public MyControlClass type. Therefore, even if you took generics and MyReturnTypeClass out of the "equation", it still wouldn't work.
However, with generics, even if no member of the public interface of the class actually uses the generic type, the type must still be at least as accessible as the derived type. For instance:
Public Class MyBase(Of T)
' T not actually used at all
End Class
Friend Class MyOtherType
End Class
Public Class MyDerived
Inherits MyBase(MyOtherType) ' Won't compile because MyOtherType is less accessible
End Class
The base class must be at least as accessible as the derived class. This is a language restriction (see here).
If you intend to avoid MyBaseClass being instantiated by consumers, consider marking it Public MustInherit instead of Friend. Hope this helps.
I have a parent class that is also a factory. For example:
Public Class Factory
Public Function clone() as Factory
' Some logic here
' return something
End Function
Public Function all() as List (Of Factory)
' Some logic here
' return something
End Function
End Class
And then an inherited one
Public Class BookFactory
inherits Factory
End Class
I can use inflection in the Factory class to generate the proper extended objects when called by the inherited one. myBookFactory.clone() will then return a BookFactory instance and not only a Factory instance.
The problem: this BookFactory instance will be cast as Factory, since the type of the function is Factory and not BookFactory.
I'd like to do something like
Public Class Factory
Public Function clone() as Me.GetType()
' Some logic here
' return something
End Function
Public Function all() as List (Of Me.GetType())
' Some logic here
' return something
End Function
End Class
So the returned value would be correctly cast and avoid having to do this each time:
Dim myBookFactory2 = DirectCast(myBookFactory1.clone(), myBookFactory1.getType())
How can I do this?
This seems to be a variation on asking for covariant return types. As you have noticed, this is not supported by VB.NET (or C# for that matter). Typically this is asked in the context of overriding virtual methods, where it is still not allowed. There are several alternatives, each with their own pros and cons.
Use a generic template argument to specify the derived class
This is similar to the way IComparable<T> is most commonly implemented.
Public Class Factory(Of T As Factory)
Public Function Clone() As T
'use GetType(T) to determine derived type
End Function
End Class
Public Class BookFactory
Inherits Factory(Of BookFactory)
End Class
Additionally, if you can add a New constraint to the Factory (eg: Factory(Of T {New, Factory(Of T)})) base class, you may be able to avoid using reflection.
However, this does not prevent the accidental (or potentially malicious) mistake of declaring a class like this:
Public Class EvilFactory
Inherits Factory(Of BookFactory)
'hmmm, now clone will be making the wrong type
End Class
Also, this approach makes it impossible to create a list of factories of different types without resorting to another base class below Factory(Of T) or declaring the list as being of object.
Make new methods on the derived classes that return the specific type you want.
Public Class Factory
Public Function Clone() As Factory
'create derived class, but return as base
End Function
End Class
Public Class BookFactory
Inherits Factory
Public Function CloneBooks() As BookFactory
Return CType(Me.Clone(), BookFactory)
End Function
End Class
This allows you to hide the cast for those times when you know you have a BookFactory and want to get another BookFactory. It also lets you treat all factory types polymorphically in the normal inheritance sense. However, if you have an object typed as Factory, you will still get back an object type as Factory.
Reconsider the inheritance relationship
Depending on how these classes are used, it may not make sense to use the inheritance relationship here. If you are only concerned with not retyping code, you may want to look into code generation instead.
You could potentially use generics to make the problem easier, but it won't remove the requirement to cast at some point. For example:
Public Class Factory(Of T)
Public Function clone() As Factory(Of T)
' Some logic here
' return something
End Function
Public Function all() As Collections.Generic.List(Of T)
' Some logic here
' return something
End Function
End Class
Public Class BookFactory
Inherits Factory(Of Book)
End Class
What is the difference between a class with protected constructors and a class marked as MustInherit? (I'm programming in VB.Net but it probably equally applies to c#).
The reason I ask is because I have an abstract class that I want to convert the constructors to shared/static methods. (To add some constraints).
I can't do this because it's not possible to create an instance in the shared function.
I'm thinking to just remove the MustInherit keyword. Will this make any difference?
Thanks.
ETA:
I think i've answered my question, If I remove the MustInherit keyword, I can no longer include the MustOverrides, which are very useful.
With that in mind, is there any way around my problem?
ETA2:
To clarify, I can't do the below unless I remove the MustInherit keyword?
Public MustInherit MyBaseClass
Private Sub New()
End Sub
Protected Function CreateInstance(ParmList) As MyBaseClass
If ParmList is Ok Then Return New MyBaseClass()
End Function
End Class
You can call the Protected constructor using reflection and instantiate the class but you can't instantiate an abstract class in this way. You can declare MustOverride methods in MustInherit classes but Protected constructor can enforce nothing on derived classes.
You should always declare classes that are conceptually abstract as MustInherit. Protected constructors can be useful when you are providing it along with some Public overloads to provide some more functionality to derived classes.
If the class only has a protected constructor, it is still possible to have an instance of the class which can stand on its own. It would require working around the protected constructor, such as using reflection.
If the class is marked as MustInherit, it is impossible to have an instance of that class on its own. Instances can only be created of the derived/inherited classes.
Not really sure what you want.
If you need to create an object of the abstract class, I recommend you create a private class implementation of your abstract class and return it in your CreateInstanceMethod:
Public MustInherit MyBaseClass
Private BaseClassImplementation
Inherits MyBaseClass
...
End Class
Public Function CreateInstance(paramList) as MyBaseClass
If paramList Is Ok Then Return New BaseClassImplementation
End Function
End Class
However, if you want to add some constraints to the construction, I recommend to throw exceptions:
Public MustInherit MyBaseClass
Protected Sub New(paramList)
If paramList IsNot Ok Then Thow New Exception
...
End Sub
End Class