How Do I cast between 2 types that implement the same interface - vb.net

I have a overlapping data objects that need to be given to at least one, possibly more, of several calculation methods to produce a common data object.
I think this is best solved by implementing both covarriance contravariance but I haven't been able to wrap my head around how what that would look like so I am open to other suggestions. In reality Animal/IAnimal and Noise have a lot of data properties so I'd like to avoid mapping them in constructors as much as possible.
Public Class Noise
Public Property Sound() As String
Public Sub Listen()
Console.WriteLine(sound)
End Sub
End Class
Public Interface IAnimal
Function Speak() As Noise()
Property Name() As String
End Interface
Public Class Dog
Implements IAnimal
Public Function Speak() As Noise() Implements IAnimal.Speak
return { new Noise() with { .Sound = "Bark" } }
End Function
Public Property Name As String Implements IAnimal.Name
End Class
Public Class Cat
Implements IAnimal
Public Function Speak() As Noise() Implements IAnimal.Speak
return { new Noise() with { .Sound = "Meow" } }
End Function
Public Property Name As String Implements IAnimal.Name
End Class
The below test produces the right output, and also works if IAnimal were an abstract base class with abstract function speak. If I understand correctly this means the covariant behavior is achieved, since it is kind of what you expect from inheritance.
Public Sub ListenToAnimalsTest()
dim spot = new Dog() With {.Name = "Spot" }
dim kitty = new Cat() With {.Name = "Kitty" }
Dim animalList As List(of IAnimal)
animalList.Add(spot)
animalList.Add(kitty)
For Each animal in animalList
Console.WriteLine(animal.Name)
animal.Speak().Listen()
Next
End Sub
The problem is I also need a CatDog that is an IAnimal
Public Class CatDog
Implements IAnimal
Public Overrides Function Speak() As Noise() Implements IAnimal.Speak
dim myself As Cat = me
dim andI As Dog = me
Return { myself.Speak(), andI.Speak()}
End Function
Public Property Name As String Implements IAnimal.Name
End Class
I'm trying to work out if I can use contravariance to allow casting Animal or IAnimal to Cat or Dog, obviously only populating the common properties.
Any thoughts or suggestions?
With regard to Decorator / Visitor Pattern I want to be able to continue whatever pattern ends up implemented by making another implementation of the parent or interface so that making the animals speak doesn't change. That means the catDog implementation of Decorator still needs to treat the IAnimal as a cat and then a dog or else I am replicating how to bark and meow in two places am I not?

Covariance and contravariance are properties of generic types (e.g. List(Of IAnimal)), which isn't really relevant to your question.
VB.NET doesn't allow true multiple inheritance, but you can create interfaces ICat and IDog that each implement IAnimal. Then you use explicit interface implementations to have your IAnimal bark or meow depending on which interface your object has been cast as.

Related

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.

Issue with generics, interfaces, and casting

I recently added an interface to some custom user controls I have implemented. The interface is pretty basic. It has one method that supports chaining:
Public Interface IMyInterface(Of T As WebControl)
Function DoSomething() As T
End Interface
The implementations are also pretty basic:
Public Class MyCustomControl
Inherits CompositeControl
Implements IMyInterface(Of MyCustomControl)
Public Function DoSomething() As MyCustomControl _
Implements IMyInterface(Of MyCustomControl).DoSomething
' do stuff
Return Me
End Class
Everything works fine up to this point. The issues arise when I attempt to loop over a collection of controls that all implement the IMyInterface interface, like so:
Dim myList = New List(Of IMyInterface(Of WebControl))
myList.Add(someCustomControl)
myList.ForEach(Sub(i) i.DoSomething())
someCustomControl is a MyCustomControl which implements IMyInterface(Of MyCustomControl) instead of IMyInterface(Of WebControl).
I am getting this error on the second line (where I try to add someCustomControl):
Option Strict On disallows implicit conversions from 'MyCustomControl' to 'IMyInterface(Of WebControl)'.
Is there any way to get around this error? I am close to having it working but I do not know enough about generics to get beyond this point.
Covariance is a language feature that was introduced in VS 2010, and solves your problem. You need to define your generic such that the type T has the Out keyword in front of it:
Public Interface IMyInterface(Of Out T As WebControl)
Function DoSomething() As T
End Interface
When you use the Out keyword, you are using covariance. It allows generics of a more derived type to be used in place of a generic with the base type. So in your case it will allow a IMyInterface(Of MyCustomControl)) object in places where the code would normally expect IMyInterface(Of WebControl)), such as your for loop.
Note that covariance has a restriction. The covariant type T can only be used as a function return value, and not as a parameter into a function (or sub). For example, if the DoSomething signature in IMyInterface looked like this the compiler would complain:
' Here the type T is used as an input param - compiler error
Sub DoSomething(ByVal sampleArg As T)
Given your chaining scenario, I don't think the above restriction is a problem.
More Info at MSDN:
Covariance and Contravariance
Creating Variant Generic Interfaces
I don't know what your function DoSomething does, but I try assigning the instance's CssClass in there for testing purpose.
Declare the interface as follows:
Public Interface IMyInterface(Of Out T As WebControl)
Function DoSomething() As T
End Interface
Notice the Out T parameter.
Create 2 controls that implement the interface:
Public Class MyCustomControl1
Inherits CompositeControl
Implements IMyInterface(Of MyCustomControl1)
Public Function DoSomething() As MyCustomControl1 Implements IMyInterface(Of MyCustomControl1).DoSomething
' do stuff
Me.CssClass = "XXX"
Return Me
End Function
End Class
Public Class MyCustomControl2
Inherits CompositeControl
Implements IMyInterface(Of MyCustomControl2)
Public Function DoSomething() As MyCustomControl2 Implements IMyInterface(Of MyCustomControl2).DoSomething
' do stuff
Me.CssClass = "YYY"
Return Me
End Function
End Class
On a test page's PageLoad event:
Dim someCustomControl As New MyCustomControl1
Dim someCustomControl2 As New MyCustomControl2
Dim myList = New List(Of IMyInterface(Of WebControl))
myList.Add(someCustomControl)
myList.Add(someCustomControl2)
myList.ForEach(Sub(i) Literal1.Text &= i.DoSomething.CssClass & "<br />")
The result is, the CssClass property of both someCustomControl & someCustomControl2 are set to the respective values.
This shows that the interface function DoSomething was successfully called and the instance changed.
You will need to cast the object before adding it:
myList.Add(CType(someCustomControl, IMyInterface(Of WebControl)))
You may also want to concider making the interface not generic and your "DoWork" method return type as the interface itself.
Public Interface IMyInterface
Function DoSomething() As IMyInterface
End Interface
When you have to specify the type in the interface definition it kind of takes away from the power of interfaces (not having to know about the implementation).

VB.NET - Misusing instance variables?

Please take a look at the code below:
Public Class A
Public person1 As Person
End Class
Public Class B
Inherits A
Public Function CheckGender() As Boolean
If person1._Gender = "M" Then
CheckGender = True
End If
End Function
End Class
Public Class C
Inherits B
Public Function CheckAge() As Boolean
If person1._Age > 30 Then
CheckAge = True
End If
End Function
End Class
Public Class D
Inherits C
Public Sub SomeMethod()
Dim list As List(Of Person) = New List(Of Person)
Dim p1 As New Person("Ian", "M", 31)
Dim p2 As New Person("Susan", "F", 20)
Dim p3 As New Person("Mark", "M", 22)
list.Add(p1)
list.Add(p2)
list.Add(p3)
For Each Person As Person In list
person1 = Person
If CheckAge() And CheckGender() Then
'Do something
End If
Next
End Sub
Public Shared Sub Main()
Dim d As New D
d.SomeMethod()
End Sub
End Class
Public Class Person
Public _Name As String
Public _Gender As String
Public _Age As String
Public Sub New(ByVal Name As String, ByVal Gender As String, ByVal Age As Integer)
_Name = Name
_Gender = Gender
_Age = Age
End Sub
End Class
c.SomeMethod loops through three persons and does two checks: b.CheckGender and c.CheckAge. CheckGender and CheckAge use an instance variable from the superclass A.
The code in the live environment loops through 100,000 records daily in a database and deletes those where CheckGender and CheckAge are both true. Is it a bad design choice to use instance variables in this scenario? I was always taught to use local variables. I would expect the Person object to be passed to CheckGender and CheckAge on each loop. Or does it really not matter?
Please note that the above code is a hypothetical example. CheckGender and CheckAge are complex functions in the actual application.
As long as CheckGender and CheckAge are not accessing any private, protected or internal member of the classes in hierarchy, and are public functions, and their logic is the same for any instance, being A, B, or C, it is a better design to have these methods in another class. Make them static if possible. You can have them accept the most general implementation of your classes (A for instance) that allows checking either the age or gender. Taken from your code, you can even pass the Person property instead of using any of the A, B and C classes.
Use of inheritance in the above case and such logic is permitted though, as long as you need to do any or all of the following:
Conform to a specific interface or base class, that A, B and C classes have to implement/extend, and that interface or base class provides the CheckGender and CheckAge methods. This can be the only solution if you pass your objects to 3rd party API, that accepts the base class/interface as an argument and internally calls the check methods.
Here is example in C#:
public static class CheckUtil
{
public static bool CheckAgeOfPerson(Person p)
{
return p.Age > 30;
}
public static bool CheckAgeOfObject(A obj)
{
// NOTE: obj.person1 must be accessible - by being either public or internal.
// If this class is in another assembly, internal is not useful
return CheckAgeOfPerson(obj.person1);
}
}
A objA = ...;
B objB = ...;
C objC = ...;
CheckUtil.CheckAgeOfObject(objA);
CheckUtil.CheckAgeOfObject(objB);
CheckUtil.CheckAgeOfObject(objC);
CheckUtil.CheckAgeOfPerson(objA.person1);
CheckUtil.CheckAgeOfPerson(objB.person1);
CheckUtil.CheckAgeOfPerson(objC.person1);
Provide specific implementation to the classes. If you have to some logic in CheckAge for instances of A, but either completely different validation for instances of B, or a combination of the existing and some new logic in C, then inheritance is your friend. Still, if that is the case, I'd prefer exposing the CheckGender and CheckAge to interface and call them via the interface. That way, inheritance is valid, but not mandatory, as long the interface is satisfied.
here is an example in C#:
public interface IGenderCheckable
{
bool CheckGender();
}
public interface IAgeCheckable
{
bool CheckAge();
}
public class A : IAgeCheckable, IGenderCheckable
{
public virtual bool CheckGender()
{
return this.person1.Gender.Equals("M");
}
public virtual bool CheckAge()
{
return this.person1.Age > 30;
}
}
public class B : A
{
public override bool CheckAge()
{
// combine custom logic with new logic
return this.person1.Age < 0 || base.CheckAge();
}
}
For complex scenarios, a combination of both approaches might be also used (of course for far more complex cases than age and gender checks):
public class A : IAgeCheckable, IGenderCheckable
{
...
}
public static class CheckUtil
{
public static bool CheckAge(IAgeCheckable obj)
{
return obj.CheckAge();
}
public static bool CheckGender(IGenderCheckable)
{
return obj.CheckGender();
}
}
About usage of instance variables vs local variables - there is a drawback in performance of using instance variables in .NET especially when they are value types. Use of local member that is int _someIntMember for example gets translated to this._someIntMember - which in turn calls the heap to get the this object, and then accesses its _someIntMember member. Having the member as a local variable, puts its value in the stack, and reads it from there without the unnecessary roundtrip trough the heap. Moreover, the stack is faster than the heap.
However, I cannot say whether too much heap usage is an abuse of it, neither a misuse of local variables when they are used too much. This depends on the performance needed, and the complexity of code. Sometimes local variables make the code more-readable, but if too many, you could easily forget what each one was (and that can be more serious issue than the negligent performance gain). So it is a matter of style and necessity.
In case you're interested in "fixing" your code to make Person a Property rather than a field, change the implementation of Class A as follows:
Public Class A
Public Property Person1 As Person
Public Overridable Function ComputeAge() As Integer
Return Person1.Age
End Function
End Class
The benefit here is you have the ability to add additional abstractions over getting and setting this property down the road if you need to. The compiler will generate a hidden private backing field for the auto property. You would still access the Person1 from any implementing classes:
Public Class B
Inherits A
Public Overrides Function ComputeAge() As Integer
Return MyBase.Person1.Age.AddYears(1)
End Function
End Class

Error when passing friend class as type from public class to friend base class

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.

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