Shadow and Overload Is Nothing [duplicate] - vb.net

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.

Related

VS suggests to override a shadowing function, but refuses to accept the Overrides declaration. How do I fix this?

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.

Implement interface in abstract class for derived classes

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.

Can I override an interface property?

Shell example is below. Basically, I want a client and employee to implement the SSN property from IPerson. However, I want client to have get and set (which isn't an issue), but I want employee to have get only.
Public Interface IPerson
Property SSN As String
End Interface
Public Class Client
Implements IPerson
Public Property SSN As String Implements AELName.IPerson.SSN
Get
Return _SSN
End Get
Set(value As String)
_SSN = value
End Set
End Property
End Class
Public Class Employee
Implements IPerson
Public Readonly Property SSN As String Implements AELName.IPerson.SSN
Get
Return _SSN
End Get
End Property
End Class
Employee generates an error of "'SSN' cannot implement 'SSN' because there is not matching property on interface 'IPerson'". Is there a somewhat simple way to override the SSN implementation for Employee?
You can implement an empty Set - one that doesn't update anything.
Public Class Employee
Implements IPerson
Public Readonly Property SSN As String Implements AELName.IPerson.SSN
Get
Return _SSN
End Get
Set
' Make read only for Employee
End Set
End Property
End Class
I would suggest splitting the interface into IReadablePerson and IReadWritePerson, with the latter inheriting the former. Note that the former interface is not IImmutablePerson, since the latter name would imply to consumers of the class that they should not expect any of its properties ever to change; an object which implements IReadWritePerson would not abide such expectation, but would abide the expectation that the person should be readable.
One slight annoyance with splitting the interface is that it will be necessary for the IReadWritePerson to include the modifier Shadows in the declarations of its read/write properties, and implementers of IReadWritePerson will have to provide both a read-only implementation of IReadablePerson and a read-write implementation of IReadWritePerson. In C#, a public implementation of a read-write property can automatically generate implementations for any like-named read-only, write-only, or read-write properties which are part of any interfaces the class implements, but when explicitly declaring which interface is being implemented, the style of the interface (read-only, write-only, read-write) must precisely match that of the implementation. Annoying.
The annoyance is made worse by the fact that one cannot simply declare IReadableFoo with a read-only property, IWriteOnlyFoo with a write-only property, and have IReadWriteFoo simply inherit both. If an interface implements a read-only property and a write-only property with the same name, neither property will be usable because the compiler will announce that in statements like somevariable = object.someProperty or someObject.someProperty = someVariable, it's "ambiguous" which implementation to use. Not that I can see any ambiguity--I can't see how the first could use anything but a getter, or the latter anything but a setter, but the compiler can't resolve it.
To answer your title question "Can I override an interface property" ... Absolutely. Here's an example of how to do so. You simply add the Overridable keyword to your base concrete implementation. I know that doesn't solve changing the property to ReadOnly, but I figured I'd point out that overriding a base classes concrete implementation of an interface is possible.
Module Module1
Sub Main()
Dim iEntity As IEntity = New MyEntity
iEntity.SetMessage(iEntity)
Console.WriteLine(iEntity.Message)
Console.ReadKey()
End Sub
End Module
Public Interface IEntity
Property Message As String
Sub SetMessage(entity As IEntity)
End Interface
Public Class MyEntity
Inherits BaseEntity
Public Overrides Property Message As String
Get
Return String.Format("{0}.. and overroad.", MyBase.Message)
End Get
Set(value As String)
MyBase.Message = value
End Set
End Property
Public Overrides Sub SetMessage(entity As IEntity)
Me.Message = "I was set from MyEntity."
End Sub
End Class
Public Class BaseEntity
Implements IEntity
Public Overridable Property Message As String Implements IEntity.Message
Public Overridable Sub SetMessage(entity As IEntity) Implements IEntity.SetMessage
Me.Message = "I was set from BaseEntity."
End Sub
End Class

Can anyone spot the issue with this VB.Net code?

I'm writing some code in VB.Net which I hope demonstrate to colleagues (not to say familiarise myself a little more) with various design patterns - and I'm having an issue with the FactoryMethod Pattern.
Here's my code:
Namespace Patterns.Creational.FactoryMethod
''' <summary>
''' This is the Factory bit - the other classes are merely by way of an example...
''' </summary>
Public Class CarFactory
''' <summary>
''' CreateCar could have been declared as Shared (in other words,a Class method) - it doesn't really matter.
''' Don't worry too much about the contents of the CreateCar method - the point is that it decides which type
''' of car should be created, and then returns a new instance of that specific subclass of Car.
''' </summary>
Public Function CreateCar() As Car
Dim blnMondeoCondition As Boolean = False
Dim blnFocusCondition As Boolean = False
Dim blnFiestaCondition As Boolean = False
If blnMondeoCondition Then
Return New Mondeo()
ElseIf blnFocusCondition Then
Return New Focus()
ElseIf blnFiestaCondition Then
Return New Fiesta()
Else
Throw New ApplicationException("Unable to create a car...")
End If
End Function
End Class
Public MustInherit Class Car
Public MustOverride ReadOnly Property Price() As Decimal
End Class
Public Class Mondeo Inherits Car
Public ReadOnly Overrides Property Price() As Decimal
Get
Return 17000
End Get
End Property
End Class
Public Class Focus Inherits Car
Public ReadOnly Overrides Property Price() As Decimal
Get
Return 14000
End Get
End Property
End Class
Public Class Fiesta Inherits Car
Public ReadOnly Overrides Property Price() As Decimal
Get
Return 12000
End Get
End Property
End Class
End Namespace
When I try to compile this, I am getting errors (BC30311) in the CarFactory.CreateCar telling me that it can't convert Fiesta, Mondeo, and Focus into Car. I don't see what the issue is - they're all subclasses of Car.
Doubtless I'm overlooking something simple. Can anyone spot it?
Cheers,
Martin.
Put Inherits on new line or use : to separate the class name and Inherits statement:
Public Class Mondeo
Inherits Car
...
Public Class Focus
Inherits Car
...
Public Class Fiesta
Inherits Car
...
Your Inherits keyword must be on a new line. This is documented by Microsoft on their help and Support. http://support.microsoft.com/kb/307222
Change the SavingsAccount class
definition as follows, so that
SavingsAccount inherits from Account
(note that the Inherits keyword must
appear on a new line):
The first error in the list is just the one at the lowest line number, it's not always the actual cause of the error.
Further down in the list of errors you will see (among several others) three more errors saying End of statement expected. at each of the subclasses. This is beacuse Class and Inherits are separate statements and go on separate lines:
Public Class Mondeo
Inherits Car
or:
Public Class Mondeo : Inherits Car
When you fix these errors, the classes do actually inherit from Car, and your code works.

In VB, How do you force an inherited class to use an attribute on the class?

I'm trying to force an inherited class to use a custom attribute. I'm creating a class library where the user who wants to create an item will do so, but be forced to add an attribute (or visual studio will automatically add the default attribute) to their inherited class. Here is what I'm hoping to achieve:
BaseClass.vb:
<CustomAttribute(10)> _
Public Class BaseClass
End Class
MyClass.vb:
<CustomAttribute(12)> _
Public Class MyClass
Inherits BaseClass
Public Sub New()
Mybase.New()
End Sub
End Class
So the thought is that much like when you mark a function as "MustOverride" and then the inherited class must override the function, I want the attribute to be "MustOverride" causing the inherited class to specify the value.
I've tried this, and it will work, but it would be much cleaner if I could use attributes:
BaseClass.vb:
Public MustInherit Class BaseClass
Public MustOverride ReadOnly Property CustomAttribute() As String
End Class
MyClass.vb:
Public Class MyClass
Inherits BaseClass
Public Sub New()
Mybase.New()
End Sub
Public Overrides ReadOnly Property CustomAttribute() As String
Get
Return "testing"
End Get
End Property
End Class
Thank you for any help you can provide.
Scott
Did you consider implementing an interface instead? I assume that you're using a base class as you want to provide some code in the base, if not then an Interface might be better depending on your other requirements:
Interface IBase
ReadOnly Property CustomAttribute() As String
End Interface
It's still very compact and when you type 'Implements IBase' in a new class Visual Studio will fill in the code for you.
There's no way in .NET to force a class to define an attribute at compile time. The best you'll be able to do is check at run-time whether the attribute was defined, and if not to throw an exception.