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.
Related
In my Windows Forms Control Library project is a user control and a class used by said user control.
The user control, as for my understanding, has nothing to do with my problem. Just for sake of completeness: it inherits from UserControl, as documented in the Designer.vb:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class UFB
Inherits System.Windows.Forms.UserControl
...
End Class
The class is the part in which I have problems. In it, I want to implement the IEquatable interface:
Public Class CPT
Implements IEquatable(Of CPT)
...
Public Function Equals(oOther As CPT) As Boolean _
Implements IEquatable(Of CPT).Equals
...
End Function
End Class
However, VS complains that the function 'Equals' shadows an overridable method in the base class 'Object'. To override the base method, this method must be declared 'Overrides'.
"Fine", I said, "there we go":
Public Overrides Function Equals(oOther As CPT) As Boolean _
Implements IEquatable(Of CPT).Equals
...
End Function
But now VS complains, that the function 'Equals' cannot be declared 'Overrides', because it does not override a function in a base class.
So, what is the correct way of doing this?
You should use the Overloads keyword:
Public Class CPT
Implements IEquatable(Of CPT)
...
Public Overloads Function Equals(oOther As CPT) As Boolean _
Implements IEquatable(Of CPT).Equals
...
End Function
End Class
That keyword is not required when both overloads are declared in the same type but when you overload a method declared in a base type, you need to be explicit. Now you have two Equals methods with different signatures, which is what you wanted.
Consider the following classes representing an Ordering system:
Public Class OrderBase
Public MustOverride Property OrderItem as OrderItemBase
End Class
Public Class OrderItemBase
End Class
Now, suppose we want to extend these classes to a more specific set of order classes, keeping the aggregate nature of OrderBase:
Public Class WebOrder
Inherits OrderBase
Public Overrides Property OrderItem as WebOrderItem
End Property
End Class
Public Class WebOrderItem
Inherits OrderItemBase
End Class
The Overriden property in the WebOrder class will cause an error stating that the return type is different from that defined in OrderBase... however, the return type is a subclass of the type defined in OrderBase. Why won't VB allow this?
You can't do that - it's changing the signature defined on the base. To do what you are trying to do you need to use generics:
Public Class OrderBase(Of T As IOrderItem)
Public ReadOnly Property OrderItems As IList(Of T)
End Class
My Visual Basic is rusty so hopefully that is accurate...
You cannot change the signature of your class upon overriding it. You can, however, return a derived type:
Public Overrides Property OrderItem() as OrderItemBase
Get
Return New WebOrderItem()
End Get
End Property
Public Sub Whatever()
Dim item As WebOrderItem = DirectCast(OrderItem, WebOrderItem)
End Sub
Alternatively, if you want to enforce the types more strictly, use generics with generic type constraints, as shown below:
Public MustInherit Class OrderBase(Of T As OrderItemBase)
Public MustOverride ReadOnly Property OrderItem() As T
End Class
Public Class OrderItemBase
End Class
Public Class WebOrder(Of T As WebOrderItem)
Inherits OrderBase(Of T)
Public Overrides ReadOnly Property OrderItem() As T
Get
Return New WebOrderItem()
End Get
End Property
End Class
Public Class WebOrderItem
Inherits OrderItemBase
End Class
Or do this if you don't want WebOrder to be a generic class as well:
Public Class WebOrder
Inherits OrderBase(Of WebOrderItem)
Public Overrides ReadOnly Property OrderItem() As WebOrderItem
Get
Return New WebOrderItem()
End Get
End Property
End Class
One approach is to have a protected overridable method, and then have a public non-overridable method which calls the overridable one. Any time the return value for the function in the derived class should change, have a notoverridable override of the overridable method call a new overridable method which returns the more refined type, and also shadow the earlier version of the public function with one that uses the new override. If vb.net allowed one class to both override and shadow the same member, things would be much cleaner, but there's no way to do that.
Public Class CarFactory
Protected Overridable Function DerivedMakeCar() as Car
' make a car
End Function
Public Function MakeCar() as Car
Return DerivedMakeCar()
End Function
End Class
Public Class FordFactory
Inherits CarFactory
Protected Overrides Function DerivedMakeCar() As Car
Return DerivedMakeFord()
End Function
Protected Overridable Function DerivedMakeFord() As Ford
' Make a Ford
End Function
Public Shadows Function MakeCar() As Ford
Return DerivedMakeFord()
End Function
End Class
A simpler alternative in some cases may be to have a public overridable MakeCar() function which always returns an object of type Car, but have a FordFactory also include a MakeFord() function which returns a Ford.
The overridden MakeCar() function would be NotOverridable and would simply call MakeFord. In some ways, the latter approach can be cleaner, but if there's a common naming convention (e.g. factories have a MakeProduct method which returns the most derived type) it may be useful to use Shadows.
I am currently working in Visual Studio 2013 with VB on .NET 4.5. I have an abstract base class which holds a collection of another abstract base class, like this:
Generic Base Class:
Public MustInherit Class CustomCollection(Of collectionItemType As CollectionItemBase)
Inherits Collections.ObjectModel.KeyedCollection(Of String, CollectionItemBase)
'...
End Class
Base Class Referened by Generic Base Class:
Public MustInherit Class CollectionItemBase
'...
End Class
I have a group of classes that inherit the generic base class "CustomCollection":
Public Class Collection1
Inherits CustomCollection(Of ClassThatDerivesFromCollectionItemBase1)
'...
End Class
Public Class Collection2
Inherits CustomCollection(Of ClassThatDerivesFromCollectionItemBase2)
'...
End Class
'etc...
This is the code I am using to try and convert an instance of Collection1 to a CustomCollection(Of CollectionItemBase):
'...
someProperty = instanceOfCollection1.Cast(Of CustomCollection(Of CollectionItemBase))
'...
This generates the following error at runtime, which to me seems to be nonsense:
"Unable to cast object of type
'd__b1`1[ApplicationName.CustomCollection`1[ApplicationName.CollectionItemBase]]'
to type
'ApplicationName.CustomCollection`1[ApplicationName.CollectionItemBase]'."
It appears to be claiming that it is unable to cast the object to its own type. Any thoughts?
When you use Cast(Of T) on an IEnumerable(Of U) it will cast every individual element to the destination type, so you should not pass the type of IEnumerable(Of T), but T itself.
In your case write your cast as
someProperty = instanceOfCollection1.Cast(Of CollectionItemBase)
This cast returns an IEnumerable(Of CollectionItemBase) that you can use.
But I don't think that was your question. Let's put that single line of code aside and talk about your question. The fact is generics don't work that way. Generic types Of Base/Derived types are totally different types.
In the simplest example, an instance of A(Of T) can't be cast to A(of U) even if T Inherits From U, because A(Of U) is a different type than `A(Of U)..
To replace class names with your real classes: an instance of
Collection1
or say
CustomCollection(Of ClassThatDerivesFromCollectionItemBase1)
can't be cast to
CustomCollection(Of CollectionItemBase)
despite of the fact that
ClassThatDerivesFromCollectionItemBase1
Inherits CollectionItemBase
because
CustomCollection(Of ClassThatDerivesFromCollectionItemBase1)
is a different type than
CustomCollection(Of CollectionItemBase).
This has nothing to do with covariance because (from MSDN):
In the .NET Framework 4, variant type parameters are restricted to
generic interface and generic delegate types.
So it won't work foe classes but works for interfaces. Let me make some changes to your code:
Public Class CollectionItemBase
End Class
Public Class ClassThatDerivesFromCollectionItemBase1
Inherits CollectionItemBase
End Class
Public Class ClassThatDerivesFromCollectionItemBase2
Inherits CollectionItemBase
End Class
Public Interface ICustomCollection(Of Out collectionItemType As CollectionItemBase)
End Interface
Public Class Collection1
Implements ICustomCollection(Of ClassThatDerivesFromCollectionItemBase1)
End Class
The Out modifier in this line
Public Interface ICustomCollection(Of Out collectionItemType As CollectionItemBase)
makes the type parameter covariant, meaning that if you have
Dim instanceOfCollection1 As New Collection1
these two lines will work:
Dim x As ICustomCollection(Of CollectionItemBase) = instanceOfCollection1
Dim y As ICustomCollection(Of Item1) = instanceOfCollection1
Hope that was helpful
This question already has answers here:
Partial Classes, LINQ, Interfaces and VB.NET
(2 answers)
Closed 2 years ago.
OK, I have to begin saying that I'm working with Visual Basic. The problem is that I have a Entity Framework object and I want to indicate that this object implements a interface, for example:
Public Interface ICatalog
Property created_at() As Date
Property id() As Long
End Interface
Those properties are allready in the object. In c# I've done this just by declaring a partial class of the object and indicates that implements that interface, but in basic is not working, I supouse that is because of the language sintaxis used to declare that a property is implementing some property of the interface, for example:
Public Property created_at() As Date Implements ICatalog.created_at
So is there any other way to accomplish this?
Take a look at this example.
Namespace MyAppDomain
Public Interface IFoo
Sub Bar()
End Interface
Public Interface IPerson
Function Gender() As String
End Interface
Public Class MyFooPerson : Implements IFoo, IPerson
Public Sub New()
End Sub
Public Sub Bar() Implements IFoo.Bar
End Sub
Public Function Gender() As String Implements IPerson.Gender
Return Nothing
End Function
End Class
End Namespace
You'll notice the MyFooPerson Class implements the IFoo Interface as well as the IPerson Interface. Each method then implements the corresponding Interface method.
Your example doesn't say whether or not the Class containing Public Property created_at() As Date Implements ICatalog.created_at is Implementing the ICatalog Interface.
I have BaseAbstractClass(of T as WebControl) (VB Generics) which inherits WebControl.
BaseAbstractClass is inherited by ConcreteWrapper1, ConcreteWrapper2, and lastly, to shake things up a bit, ConcreteWrapper4. Each of these would inherit BaseAbstractClass using a different class inherited from WebControl.
What I would like to do is have factory that returns a ConcreteWrapper as a BaseAbstractClass(of WebControl). But whenever I try to return a new instance of a ConcreteWrapper I get a compile time conversion error.
[Edit: Code Added]
BaseAbstractClass
Public MustInherit Class BaseAbstractClass(Of T As WebControl)
Inherits WebControl
Protected _item As T
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
_item.RenderControl(writer)
End Sub
End Class
The other ConcreteWrappers look like this except with different CustomControl
Public Class ConcreteWrapper1
Inherits BaseAbstractClass(Of CustomControlInheritedFromWebControl1)
Public Sub New(ByVal control As CustomControlInheritedFromWebControl1)
MyBase._item = control
End Sub
End Class
Public Class CustomControlInheritedFromWebControl1
Inherits WebControl
//not the correct comment markers but the coloring works better
//do stuff here... Implm not important.
End Class
My Factory
Public Class WebControlFactory
Public Shared Function GetWebControl() As BaseAbstractClass(Of WebControl)
Return New ConcreteWrapper1(New CustomControlInheritedFromWebControl1())
End Function
End Class
[/Edit]
Could I get an explanation of what's going on and why that won't work (and possibly, a solution)?
Thanks!
ConcreteWrapper1 does not inherit from BaseAbstractClass(of WebControl), instead it inherits from BaseAbstractClass(of T)
BAC(of WebControl) is not interchangable with BAC(of T).
If you must use inheritence, you need two levels of abstraction.
WebControl
BAC inherits WebControl
BAC(of T) inherits BAC
Wrapper1 inherits BAC(of int)
Wrapper2 inherits BAC(of string)
Wrapper3 inherits BAC(of Foo)
Wrapper4 inherits BAC(of Bar)
Then you may return all instances of your Wrappers as BAC.
The reason is phrased well by Zooba:
You cannot cast between generic types with different type parameters. Specialized generic types don't form part of the same inheritance tree and so are unrelated types.