Change inheritance class at runtime - vb.net

I have two class with code like this (it's just example)
class parent1
function f(param as integer) as integer
return param +2
end function
end class
'===============================
class parent2
function f(param as integer) as integer
return param *1
end function
end class
then i want to create a class inherits of one of boot based on situation at run time. maybe like this:
class child
sub new(s as string)
'it will inherits parent1
end sub
sub new(i as integer)
'it will inherits parent2
end sub
end class
Is it possible..?

.NET languages do not support multi inheritance and you cannot change it during runtime as pointed out in all comments you got.
Instead, nice "workaround" was created for this problem called Interface. Somebody call it a "hack" solution :)
For me your problem is a problem for dependency injection.
You want have child class which can change behavior during runtime.
Create abstraction of behavior, you want to change, as interface
Public Interface IBehavior
Function Calculate(value As Integer) As Integer
End Interface
Then create child class which takes behavior as constructor parameter
Public Class Child
Private ReadOnly _behavior As IBehavior
Public Sub New(behavior As IBehavior)
_behavior = behavior
End Sub
Public Sub Execute(int value)
Dim newValue As Integer = _behavior.Calculate(value)
' Do something else
End Sub
End Class
Create implementations of IBehavior you want to use during runtime
Public Class SumBehavior Implements IBehavior
Function Calculate(value As Integer) As Integer Implements IBehavior.Calculate
Return value + 2
End Function
End Class
Public Class MultiplyBehavior Implements IBehavior
Function Calculate(value As Integer) As Integer Implements IBehavior.Calculate
Return value * 2
End Function
End Class
Then during runtime you can change behavior of Child instance based on passed parameter
Dim sum As New SumBehavior()
Dim child As New Child(sum)
child.Execute(23)
Your problem is good example of "Open-Close Principle".
- Your Child class is closed for modifications -> Do something else staff in Execute method stays unmodified
- Your child class is open for modifications -> Behavior logic can be changed without touching Child class

Multiple inheritance is not possible in .Net. Now, to solve your problem
Try Dynamic Source Code Generation and Compilation. You can not do multiple inheritance but during runtime when its sure which type of class has to be inherited, dynamically create the class using CodeDom. Refer msdn link
This approach may or may not suit your need. Still if you have an scope to change the design, Use interfaces and dependency injection. (Since the function name is same in both the classes parent1 and parent2 you can take advantage of polymorphism).

Related

How can I access base class from List(of derived classes) using iteration?

I collected different derived class instances using a List(Of Interface).
And naturally I only can access the Interfaced methods using iteration.
Public Class Base
Public Sub Work_inBase()
End Sub
End Class
'--------------------------
Public Interface MyIFC
Sub Work()
End Interface
'--------------------------
Public Class Child1
Inherits Base
Implements MyIFC
Public Sub Work() Implements MyIFC.Work
End Sub
End Class
'--------------------------
Public Class Child2
Inherits Base
Implements MyIFC
Public Sub Work() Implements MyIFC.Work
End Sub
End Class
'--------------------------
Public Sub MainProgram()
Dim C1 As New Child1()
Dim C2 As New Child2()
Dim MyList As New List(Of MyIFC)
MyList.Add( C1 )
MyList.Add( C2 )
MyList(0).Work() >>> OK because it was interfaced
MyList(0).Work_inBase() >>> does not work, cannot access to base
End Sub
Is there any other way to access to base class methods or members (which will be very large)??? Maybe different class design is required???
Thank you (vb is prefered, but I can read c# code equally too)
Obviously there is no way to know that an arbitrary List(Of MyIFC) actually contains members that are or do inherit type Base, so there's no reason that there should be any standard functionality that would give you items of that type. If you know for a fact that the items will be that type though, you can simply cast as that type when they come out, e.g.
DirectCast(MyList(0), Base).Work_inBase()
Of course, once you have a reference of type Base then you can't access members of MyIFC because Base doesn't implement that interface. Your example is very contrived so there's no way for us to know whether there's a better design possible in your specific case.

Function overloads based on interface inheritance

Say I have a base interface, and another one inheriting from it :
Public Interface Parent
{stuff}
End Interface
And
Public Interface Child
Inherits Parent
{other stuff}
End Interface
I also have a sub and its overload :
Public Sub doStuff(parameter As Parent)
{do some stuff}
End Sub
And
Public Sub doStuff(parameter As Child)
{do some other stuff}
End Sub
If I call the sub like this it calls the "child function" :
Dim myParam As Child = New SomeClassImplementingChild
doStuff(myParam)
However, is there any way to make it call the "child function" with something like this, assuming I don't know at compile time the type of the coolParameter :
Public Sub coolFunction(coolParameter As Parent)
doStuff(coolParameter)
End Sub
Dim myParam As Child = New SomeClassImplementingChild
coolFunction(myParam)
I have found a workaround which is I guess the closest I'll ever get to a solution:
doStuff(Convert.ChangeType(coolParameter, coolParameter.GetType))
That will convert to the "real" type at Runtime, effectively calling the right function. However, the functions all have to be public to be called that way

Call baseclass property

It's rather a simple question and both will work. But I'm just wondering what the best practice is. When a child class changes a variable in the baseclass. Should it call the property or just change the underlying variable.
I'm not using the property to do something with the data. The code in the child class is the same. But what is considered the best practice OOP wise?
Sample code:
Public Class TestDirect
Protected temp As Integer
End Class
Public Class TestChldDirect
Inherits TestDirect
Public Sub New()
MyBase.temp = 1
End Sub
End Class
versus
Public Class TestProperty
Private _temp As Integer
'
Public Property temp() As Integer
Get
Return Me._temp
End Get
Set(ByVal value As Integer)
Me._temp = value
End Set
End Property
End Class
Public Class TestChldProperty
Inherits TestProperty
Public Sub New()
MyBase.temp = 1
End Sub
End Class
The second approach gives you more flexibility later on and better protects/hides your underlying implementation. For instance, in your example you might want to modify the type of temp, add some validation etc. Those changes would be more difficult in your first example as you would be affecting the classes that derive from your base class. In the second example you can make the change without affecting any derived classes.

VB.NET constructors in derived classes

I have a base class that I use with reflection to fill the fields of the derived classes, reading from the database.
Public MustInherit Class DaoBase : Implements IEquatable(Of DaoBase)
Sub New()
' Empty, hate to have it
End Sub
Sub New(reader As DbDataReader)
' Reads the DB and fills the instance fields
End Sub
' More stuff...
End Class
The derived classes usually have a non-default constructor to set its fields:
Public Class Customer
Inherits DaoBase
Public Sub New(
id As Integer,
description As String)
Me.id = id
Me.description = description
End Sub
End Class
Questions:
1) I don't like to have the empty constructor in the base class. It sits there unused and could create an object in an incorrect state. If I remove it, then the compiler gives an error because, missing the default constructor, the derived class constructor should call the only-one base class constructor.
2) I can't do new Customer(myReader) because that constructor is not in the derived class, even if it's in the base class. I have to explicitly declare it, which I don't like.
Public Class Customer
Inherits DaoBase
Public Sub New(
id As Integer,
description As String)
Me.id = id
Me.description = description
End Sub
Public Sub New(reader As DbDataReader)
MyBase.New(reader)
End Sub
End Class
If your base class is filling fields in the derived class, it sounds like you should be using an interface instead of what you're doing.
As for your questions, just because you don't like it doesn't make it wrong. But as one comment said, if you change the second New to:
Sub New(Optional reader as DbDataReader = Nothing)
then you fulfill the requirement to have an empty constructor and you can have it do the right thing when no reader is given.

How can I use multiple class types in the same place

Say I have a function that does the following in Vb.net
For i as decimal = 0 to mstrItems.count - 1
mstrItems.item(i).activate
next
And I have classes as such that both classes, though different object type, have the function activate.
I would like to iterate my Items as above, having the list include any type of object, not just one specific type, and have the different objects all perform the activate function in the same way, though they are different object types.
Cheers!
Martin
Alternatively, you could define an interface and implement it in all your different Types:
Interface IActivateable
Sub Activate
End Interface
Class MyType1: Implements IActivateable
Sub Activate Implements IActivateable.Activate
'some implementation details here ...
End Sub
End Class
Class MyType2: Implements IActivateable
Sub Activate Implements IActivateable.Activate
'some implementation details here ...
End Sub
End Class
Then you can cast each type as the interface you want to handle:
Dim myList as new list(of IActivateable)
myList.add(new MyType1)
myList.add(new MyType2)
for each obj as IActivateable in myList
obj.Activate
end for
To give you some searchable terminology, what you're looking to do is use polymorphism to make use of the Strategy Pattern.
At its simplest, what you want is to have a base class (possibly abstract, I don't know the VB terminology for these things though) from which your multiple classes inherit. It's a kind of high-level abstraction which represents the common functionality between those classes. Something like this:
Class Car
Overridable Sub Drive()
Throw New NotImplementedException
End Sub()
End Class
Class GasPoweredCar
Inherits Car
Overrides Sub Drive()
' logic for driving a gas-powered car
End Sub
End Class
Class SolarPoweredCar
Inherits Car
Overrides Sub Drive()
' logic for driving a solar-powered car
End Sub
End Class
And so on. The idea is that there's one common thing you're trying to accomplish (Drive in this case) but multiple different implementations would accomplish it in different ways. But since all of those implementations are still a Car then you can treat them as such (which is where polymorphism comes in).
So instead of having a list of GasPoweredCar and a list of SolarPoweredCar you can have a single combined list of Car which contains both. You don't need to know what kind of car it is in order to simply invoke the Drive function.
For i As decimal = 0 To listOfCars.count - 1
listOfCars.Item(i).Drive
Next
Or more simply:
For Each car As Car In listOfCars
car.Drive
Next
The alternative to Davids excellent answer is using Interfaces.
The GasPoweredCar and SolarPoweredCar classes could implement an interface:
interface ICar { void Drive(); }.
Both classes would have their own internal implementation of the Drive method. Then when iterating over Gas or Solar cars you could cast the class to the interface and call the method.
If David's isn't ideal I am Happy to elaborate, just let me know.
An alternative to polymorphism is to use an Interface:
Module Module1
Sub Main()
Dim lstClass As New List(Of IMyInterface)
lstClass.Add(New FirstClass("A"))
lstClass.Add(New SecondClass("B"))
lstClass.Add(New FirstClass("C"))
lstClass.Add(New SecondClass("D"))
For i As Integer = 0 To lstClass.Count - 1
lstClass(i).Activate()
Next i
End Sub
Interface IMyInterface
Sub Activate()
End Interface
Class FirstClass
Implements IMyInterface
Public Property MyProperty As String
Sub New(s As String)
MyProperty = s
End Sub
Sub Activate() Implements IMyInterface.Activate
MsgBox("First class activate: " & MyProperty)
End Sub
End Class
Class SecondClass
Implements IMyInterface
Public Property MyProperty As String
Sub New(s As String)
MyProperty = s
End Sub
Sub Activate() Implements IMyInterface.Activate
MsgBox("Second class activate: " & MyProperty)
End Sub
End Class
End Module