Storing an object that implements multiple interfaces and derives from a certain base (.net) - vb.net

In .net, it's possible to use generics so that a function can accept arguments which support one or more interfaces and derive from a base type, even if there does not exist any single type from which all valid argument types derive. For example, one could say:
Sub Foo(Of T As {IInterface1, IInterface2, SomeBaseType})(Param as T)
and be allowed to pass any derivative of SomeBaseType which implements both IInterface1 and IInterface2. This will work even if SomeBaseType does not support Interface1 and Interface2, and classes which do implement those interfaces don't share any common ancestor that also implements them.
This can be very convenient if one won't need to keep the parameter anywhere after the function has exited. Unfortunately, I can't figure out a way to persist the passed-in parameter in such a way that it can later be passed to a similar function, except perhaps by using Reflection. Is there any nice way of doing that?
The closest I've been able to come up with is to define an interface INest (perhaps not the best name--can anyone improve it?) thus:
Interface INest(Of Out T)
Function Nest() As T
End Interface
And for any interface that will be used in combination with others or with base-class "constraint", define a generic version as illustrated below
Interface IFun1
' Any members of the interface go here, e.g. ...'
Sub DoFun1()
End Interface
Interface IFun1(Of Out T)
' This one does nothing but inherit'
Inherits IFun1, INest(Of T)
End Interface
A class which will support multiple interfaces should declare itself as implementing the generic ones, with itself as the type argument.
Class test123a
Inherits sampleBase
Implements IFun1(Of test123a), IFun2(Of test123a), IFun3(Of test123a)
End Class
If that is done, one can define a function argument or class variable that supports multiple constraints thusly:
Dim SomeField as IFun1(Of IFun2(Of IFun3(Of sampleBase)))
and then assign to it any class derived from sampleBase, which implements those interfaces. SomeField will implement IFun1; SomeField.Nest will implement IFun2; SomeField.Nest.Nest will implement IFun3. Note that there's no requirement that IFun1, IFun2, IFun3, or sampleBase share any common derivation other than the generic interfaces inheriting from INest(Of T). Note also that, no matter how many INest-derived interfaces a class implements, it only needs to define one implementation of INest(Of T).Nest.
Not exactly beautiful, but there are two nice things about it: (1) any concrete class which in fact implements the necessary interfaces can be assigned directly to a field declared as above, without a typecast; (2) while fields which chain the types in a different order are not assignment compatible, they may be typecast to each other.
Is there any better way to store something in such a way that it's "known" to support multiple interfaces and derive from a certain base type? Given that one can write such code in a type-safe manner, it would seem like the .net 2.0 CLR could probably support such a thing quite nicely if compilers offered a little assistance. I'm unaware of any particularly nice approach with present compilers, though.

The best way I can think of is to make an abstract storage and generic implementation of this storage. For example (excuse my VB.NET):
MustInherit Class Storage
Public MustOverride Sub DoSomething()
End Class
Class Storage(Of T As {IInterface1, IInterface2, SomeBaseType})
Inherits Storage
Public Overrides Sub DoSomething()
' do something with Value.
End Sub
Public Value As T
End Class
And usage
Dim S As Storage
Sub Foo(Of T As {IInterface1, IInterface2, SomeBaseType})(ByVal Param As T)
S = New Storage(Of T) With {.Value = Param}
End Sub
Sub UseS()
S.DoSomething();
End Sub
Update: Ok, because we may not be able identify in advance all of the actions:
MustInherit Class Storage
MustOverride ReadOnly Property SomeBaseType As SomeBaseType
MustOverride ReadOnly Property IInterface1 As IInterface1
MustOverride ReadOnly Property IInterface2 As IInterface2
End Class
Class Storage(Of T As {IInterface1, IInterface2, SomeBaseType})
Inherits Storage
Public Value As T
Public Overrides ReadOnly Property IInterface1 As IInterface1
Get
Return Value
End Get
End Property
Public Overrides ReadOnly Property IInterface2 As IInterface2
Get
Return Value
End Get
End Property
Public Overrides ReadOnly Property SomeBaseType As SomeBaseType
Get
Return Value
End Get
End Property
End Class

Related

Enumeration vs Interface for constants

Is it a good design practice to change an enumeration type:
Public Enum EnumerationType
EnumerationMember1
EnumerationMember2
End Enum
To an interface base with implementor classes (even if they are empty)?
Public Interface IEnumerationType
End Interface
Public Class EnumerationMember1 : Implements IEnumerationType
End Class
Public Class EnumerationMember2 : Implements IEnumerationType
End Class
For extensibility purposes.
Is there any downside? Is there any case in which is preferable to use just an enum?
INTERFACES used for contracts between classes
that is when you have two non-related classes sharing some methods
Enumeration type stores special values. These are named constants. With an Enum, we replace magic constants throughout a program.
This improves code clarity,
organizes code
and makes code easier to maintain
For extensibility purposes it is better to use interface cause you will have methods properties and you can inherit the class later
Public Enum
with interface you have enumeration with advanced options so what the downsides will be ? No downside :)
It's not entire clear what you're after, but take a look at the strongly typed enum pattern.
''' <completionlist cref="EnumerationType"/>
Class EnumerationType
Private Key As String
Public Shared ReadOnly Member1 As EnumerationMember1 = New EnumerationMember1("EnumerationMember1")
Public Shared ReadOnly Member2 As EnumerationMember2 = New EnumerationMember2("EnumerationMember2")
Private Sub New(key as String)
Me.Key = key
End Sub
Public Overrides Function ToString() As String
Return Me.Key
End Function
End Class
So when you use it, it looks like an enum:
Sub Main
DoSomething(EnumerationType.EnumerationMember1)
DoSomething(EnumerationType.EnumerationMember2)
End Sub
Sub DoSomething(test As IEnumerationType)
Console.WriteLine(test.ToString())
End Sub
but you can easily add functionality to it (like explicit conversions, or a way to iterate over all members using a shared dictionary, or whatever comes to your mind).
It's typesafe, and using the magic completionlist comment will enable Intellisense support.

How do I refer to two different classes by one name in vb.net

I have two classes to handle database operations, one for MySQL (DBMySQL), and another for SQLite (DBSQLite). The user chooses which database system to use.
The functions within the classes have the same names, but are obviously slightly different to handle the variations in databases.
I would like to refer to the chosen class by one name throughout the application. I have set a global variable DB.
In a procedure I can: Dim DB as New DBMySQL (or DBSQLite). This works within the procedure, but not globally, but I can see all the functions when coding.
If I instead use: DB = New DBMySQL, this works globally, but no class functions are displayed when coding.
Any alternatives?
Use the concept of inheritance, and create a MustInherit class with MustOverride methods and/or properties.
Public MustInherit Class AbstractDB
Public MustOverride Function MyQuery(input As Object) As Object
Public MustOverride Sub MyUpdateMethod(input As Object)
End Class
Public Class DBMySQL
Inherits AbstractDB
Public Overrides Function MyQuery(input As Object) As Object
End Function
Public Overrides Sub MyUpdateMethod(input As Object)
End Sub
End Class
Public Class DBSQLite
Inherits AbstractDB
Public Overrides Function MyQuery(input As Object) As Object
End Function
Public Overrides Sub MyUpdateMethod(input As Object)
End Sub
End Class
Then, when you want to use your classes, make your DB global variable of type AbstractDB. You could then create either DBMySql or DBSQLite and assign it to your DB variable. The method names will all be the same, because they all inherit the same base class. But each derived class must fill out the content of those methods on its own.
Dim DB as AbstractDB = New DBMySQL
You could also use an interface.
Public Interface IRepository
' common functions of MySQL and SQLLiteclasses
End Interface
Public Class MySQLRepository
Implements IRepository
End Class
Public Class SQLLiteRepository
Implements IRepository
End Class
Public Function GetDB(userChoice As String) As IRepository
If userChoice = "MySQL" Then
Return New MySQLRepository()
Else
Return New SQLLiteRepository
End if
End Function
Dim DB As IRepository = GetDB(userChoice)
This is a basic implementation of the Repository pattern. The example in the link is in C#, but, as you're probably aware, it's not easy finding examples in VB. Fortunately, there are lots of C# to VB converters.
The abstract example Sean Skelly gave should also work. You may want to research the difference between abstract classes and interfaces.

Too many identical simple methods using an interface

I have a few dozen classes which all implement the same interface and many of the methods have identical implementation. I have to do a lot of copy and paste whenever I add a new class. How can I get less code duplication?
I've heard that you should put the common code in a helper class but a lot of these methods are really trivial so calling a helper method is barely any simpler than doing the actual work.
Inheritance would save re-declaring all these methods but it would make it messy for the few classes that don't have the identical implementation.
Examples:
Identical in nearly every class...
Public Sub ThingWasDeleted(ByVal deletedThing As Thing) Implements Iinterface.ThingWasDeleted
If MyThing Is deletedThing Then
MyThing = Nothing
End If
End Sub
...but occasionally different:
Public Sub ThingWasDeleted(ByVal deletedThing As Thing) Implements IInterface.ThingWasDeleted
'Do nothing
End Sub
Identical in every class but already just as simple as calling a common helper method:
Public ReadOnly Property DisplayName() As String Implements IInterface.DisplayName
Get
Return DisplayNameShared
End Get
End Property
If you put these methods in a helper class, wouldn't that make it just as messy (if not more) than having an abstract base class where you can override the base class's functionality when needed?
For example:
Public MustInherit Class BaseClass
Public ReadOnly Property DisplayName() As String
Get
Return DisplayNameShared
End Get
End Property
Public Overridable Sub ThingWasDeleted(ByVal deletedThing As Thing)
If MyThing Is deletedThing Then
MyThing = Nothing
End If
End Sub
End Class
This provide a definition of the property that all inheriting classes can use, and gives the inheriting class an option to override and create their own implementation of ThingWasDeleted.
For example:
Public Class MyClass
Inherits BaseClass
Public Overrides Sub ThingWasDeleted(ByVal deletedThing As Thing)
' Do nothing
End Sub
End Class
On the other hand, if you wrote a helper class, you'd have to define every method, and the developer (which may or may not be you) would have to know which method to change. Additionally, instead of having the option to use the existing functionality in the base (abstract) class, every class you create will have to call each of the proper helper methods.
Personally, I prefer the former option, mainly because the inheriting classes don't have to call anything to get the base functionality established in the base class, and can override what they need to on a case-by-case basis. Conversely, having them all in a helper class means you have to at least write the code to call each of the necessary helper methods in every class you have.

VB.NET Forced Inheritance through multiple generations

I'm trying to wrap my head around inheritance/interfaces/implementation a bit better in .NET.
I have a class that's defined as follows (sort of):
Public Class Sheet
Property Name As String
Property Steps As List(Of [Step])
End Class
The thing is, [Step] is just a virtual, base class. There are 5 different concrete implementations of [Step]. To make matters a bit more complex, there are 3 DIRECT implementations of [Step], 2 of which are virtual. Each of those 2 has 2 subclasses that would concretely implement [Step].
So, here's how it looks:
Step
|-----------------|-----------------|
| | |
SubStepA SubStepB SubStepC
|----|----| |----|----|
| | | |
SubStepAA SubStepAB SubStepCA SubStepCB
So, SubStepB, SubStepAA, SubStepAB, SubStepCA and SubStepCB are the concrete implementations.
There are a couple of things that I'd like ANY Step to do, such as Clone().
So, I tried declaring the following in Step:
Public MustOverride Function Clone() As Step
The problem is that, when I attempt to implement that in SubStepAA, I can't declare the following:
Public Overrides Function Clone() As SubStepAA
If I do that, I get an error that the return types aren't the same.
Is the solution to this to just use a DirectCast call anytime I clone a concrete subclass? That seems odd and unsatisfying. It also just seems wrong. I mean, if I clone a SubStepAA object, I want to get back an object of type SubStepAA.
There's got to be a way to do this, right? I mean, I guess I could just declare each class the way it needs to be, but it also seems wrong to have to write 5 DIFFERENT Clone() methods that just HAPPEN to work in (essentially) the same way (creating a deep copy of the referenced object).
I've looked into using Interface declarations, but that seems to suffer from the same type mismatch error.
Please tell me that I'm just missing something basic!
Thanks!
As an aside, I have been doing some reading and I realize that there may be more optimized ways to do deep copies of object (e.g., through serialization/deserialization), but I'm still interested in this question, even if I choose to clone objects using a different approach.
This may not be exactly what you are hoping for, but you can meet all your requirements by using a generic base type, like this:
Public MustInherit Class [Step](Of T)
Public MustOverride Function Clone() As T
End Class
Public Class StepA
Inherits [Step](Of StepA)
Public Overrides Function Clone() As StepA
' ...
End Function
End Class
However, then, there would be no common Step base class that would be usable for all the derived types. For instance, there would be no way to do something like this:
Dim s As [Step] = New StepA() 'Won't work because there is no Step type, only a generic Step(T) type
Dim c As [Step] = s.Clone()
However, if you need to have a common base type like that, you could still do something like that, albeit with some additional complication:
Public Interface ICloneable(Of T)
Function Clone() As T
End Interface
Public MustInherit Class [Step]
Implements ICloneable(Of [Step])
Public MustOverride Function CloneBase() As [Step] Implements ICloneable(Of [Step]).Clone
End Class
Public MustInherit Class [Step](Of T As [Step])
Inherits [Step]
Implements ICloneable(Of T)
Public Overrides Function CloneBase() As [Step]
Return Clone()
End Function
Public MustOverride Function Clone() As T Implements ICloneable(Of T).Clone
End Class
Public Class StepA
Inherits [Step](Of StepA)
Public Overrides Function Clone() As StepA
' ...
End Function
End Class
If you did it that way, you would have that additional layer of abstraction where you could cast each concrete object as either a Step(T) or as a Step. For instance, you could then do this:
Dim s As [Step] = New StepA()
Dim c As [Step] = s.CloneBase()
But of course, this all begs the question, is it worth all this complication? The two simpler solutions would be to implement the interface independently on each derived class (and thereby forgo the ability to call clone from the base class), or else go with your first idea and just have the Clone method always return the base type.

Can I have a function with return type of the class itself in inherited classes? VB.NET

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