vb.net class MustInherit Interface - vb.net

I'm working in VB.Net.
I have several X objects. Every one of them needs to have the Y function, so I need to choose Interface or MustInherit. I also need to have a Z function exactly the same for each object. This function is used only by the object's abstracted/implemented methods, like a printout for that kind of object.
What's the best way to do this?

I'd only use an interface if you expect there to be classes that implement Y but do not require the Z function.
I'd go with abstraction given all subclasses require the Z function. If Z is only going to be used within the class, mark it as Protected so it's only visible to subclasses.
MustInherit Class BaseX
Public MustOverride Sub Y();
Protected Sub Z()
' TODO: Implement common version of Z.
End Sub
End Class
Class FirstX Inherits BaseX
Public Overrides Sub Y()
' TODO: Implement first version of Y.
' Call Z() as required.
End Sub
End Class
Class SecondX Inherits MyBaseClass
Public Overrides Sub Y()
' TODO: Implement second version of Y.
' Call Z() as required.
End Sub
End Class
NOTE: I hope my VB is correct. I don't have it installed so I can't validate my syntax.

Don't really understand your question. If you want a good answer, you may want to make your question more clear.
From what I understand, you want to know how to use inheritance to create two+ objects which inherit the same MustInherit class and perform similar actions with different implementations.
I don't understand the difference between your X function and Z function.
Public MustInherit Class theBase
Public MustOverride Sub ZPrint()
End Class
Public Class a
Inherits theBase
Public Overrides Sub ZPrint()
' the "a" way to print
End Sub
End Class
Public Class b
Inherits theBase
Public Overrides Sub ZPrint()
' the "b" way to print
End Sub
End Class
Public Class theClass
Public Sub run()
Dim myA As theBase
Dim myB As theBase
myA = New a
myB = New b
myA.ZPrint()
myB.ZPrint()
End Sub
End Class
Make an instance of theClass and execute the run() method.

Related

vb.net extending a class with generics

is it possible to extend different classes with the same generic class?
I tried something like this:
Public Class A
Public Sub TestA()
Debug.Print("Test A")
End Sub
End Class
Public Class B(Of T)
Public Sub TestB()
Debug.Print("Test B")
End Sub
End Class
Public Class C
Inherits B(Of A)
Public Sub TestC()
TestA() '**<-- Thows error 'is not declared'**
TestB()
Debug.Print("Test C")
End Sub
End Class
I basicly have some usercontrols, which derive from Combobox or Textbox and i'd like both to implement some functions(and interfaces) that are defined in a base class. In C++ i'd do it with multi inheritance.
is it possible to extend different classes with the same generic class?
Generics isn't some kind of "workaround" for a lack of multiple inheritance, no. Your class C doesn't derive from A - it just means that the T in B(Of T) would be A in the context of C.
Which instance of A would you expect TestA() to be called on? Creating an instance of C certainly doesn't create an instance of A...
The fact that B(Of T) doesn't use T anywhere should be a warning signal - types which are generic but never use their generic type parameters are generally problematic.
It's hard to know exactly how to help you solve your real problem without more details, but you can't add a common base class in like this, when you also need to derive from other types which aren't under your control.
Perhaps extension methods would help?
You could make both your Combobox and your Textbox classes implement the same interface.
Then you could define extension methods on that interface class.
Thanks to your hint i got this working with extentions
Public Class Form1
Public Interface IA
Property val As String
End Interface
Public Class A
Public Sub test()
Debug.Print("test")
End Sub
End Class
Public Class C
Inherits A
Implements IA
Public Property val As String Implements IA.val
Public Sub TestC()
val = "testxxx"
TestA()
test()
End Sub
End Class
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim ct As New C
ct.TestC()
End Sub
End Class
Module TestModule
<Extension()>
Public Sub TestA(ByVal pvIA As IA)
Debug.Print(pvIA.val)
End Sub
End Module
This way every class can implement it's own 'parent' (like A here) and i don't need to implement the function TestA for every class.
thank you

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

VB.net abstract class understanding

If I have a class called A and a class called B, if B inherits A that means A is the super class and B is the subclass. I have been asked to describe why class A is not an abstract class but as i see it class A is an abstract class A, as it has been created for Class B to use in the future, is it something to do with Class B not being able to access the fields in Class A as although they are private by default?
Class A looks something like this
Public Class A
StartDate As Date
Men As Integer
Place As String
Public Sub New()
StartDate = Today
Men = 0
Place = ""
End Sub
End Class
Class B Looks like this
Public Class B inherits Class A
Grade As ExamGrade
Public Sub New()
MyBase.New
StartDate = Today
Men = 0
Place = ""
Grade = 'Easy'
End Sub
Public Function setGrade(grade As String)
ExamGrade = grade
End Function
End Class
In order to be abstract, class A must have the MustInherit keyword.
Abstract (MustInherit) means that this class serves as base class only and cannot be instantiated with New. It also allows you to declare abstract (MustInherit) members with no implementation, i.e. no method body. The inheriting classes then must override the abstract members and provide an implementation unless they are abstract themselves (where a third level of deriving classes would then provide an implementation).
Note that you are allowed to call an abstract member. At runtime the implementation of the actual implementing class will be called.
See: MustInherit (Visual Basic)
Members are private if not specified otherwise. Specify them to be Protected to allow descendant classes to see them or Public to allow "everybody" to see them.
See: Access Levels in Visual Basic
Public MustInherit ClassA
Protected StartDate As Date
Protected Men As Integer
Protected Place As String
Public Sub New()
StartDate = Today
Men = 0
Place = ""
End Sub
Public MustOverride Sub Print()
End Class
Public ClassB
Inherits ClassA
Public Grade As String
Public Sub New()
MyBase.New() 'This initializes StartDate, Men and Place
Grade = "Easy"
End Sub
Public Sub SetGrade(ByVal grade As String)
Me.Grade = grade
End Sub
Public Overrides Sub Print()
Console.WriteLine($"Grade = {Grade}")
End Sub
End Class
Now, you can use it like this
Sub Test(ByVal a As ClassA)
a.Print()
End Sub
You can call Test by passing it a ClassB object.
A is not abstract. Abstract means you cannot instantiate the class. It means you MUST inherit it.
Use the abstract keyword to make the class abstract. You can also make methods abstract as well.
If you want B to see certain methods in A, but not to anyone else, use protected keyword.
Sorry, VB uses the MustInherit and MustOverride keywords.

Similar classes with different signatures

I have two classes:
Public Class Subscribing
Private _subscribingObjects As IList(Of String)
Public Sub Add(ByVal obj As SubscribeObject)
'...code...'
End Sub
Public Sub Remove(ByVal index As Integer)
'...code...'
End Sub
End Class
Public Class Providing
Private _providingObjects As IList(Of String)
Public Sub Add(ByVal obj As ProvideObject)
'...code...'
End Sub
Public Sub Remove(ByVal index As Integer)
'...code...'
End Sub
End Class
Is there a more elegant way to add do this? One class would suffice, but since the Add methods have different arguments, then one really wouldn't work.
Any help would be appreciated.
this?
Public Class SubscribingProviding(Of t)
Private _subscribingObjects As IList(Of String)
Public Sub Add(ByVal obj As t)
'...code...'
End Sub
Public Sub Remove(ByVal index As Integer)
'...code...'
End Sub
End Class
Your add functions should be fine. As long as you have different variable types being passed in you can have the function names be the same. Your remove Subs will not be allowed in the same class because it is using the same parameter Integer.
Eh.. probably not. They are different enough that you cant even Interface them.
I personally wouldn't mix the two responsibilities (of subscribing and providing) in one class. The classes themselves can easily be simplified by just inheriting from List(Of T)
Public Class Subscribing
Inherits List(Of SubscribeObject)
End Class
Public Class Providing
Inherits List(Of ProvideObject)
End Class
If you really want to get down to one class and make sure that it can only accept SubscribeObject and ProvideObject respectively, implement a common interface in both SubscribeObject and ProvideObject. Then create a generic class that accepts the interface:
' Common interface '
Public Interface ISubscribeProvideObject
End Interface
' SubscribeObject and ProvideObject both implementing the common interface '
Public Class SubscribeObject
Implements ISubscribeProvideObject
'...'
End Class
Public Class ProvideObject
Implements ISubscribeProvideObject
'...'
End Class
' Generic class accepting both types '
Public Class SubscribingProviding(Of T As ISubscribeProvideObject)
Inherits List(Of T)
'... Add() and Remove() methods only needed if custom logic applies ...'
End Class

Is there a way to make a value accessible only to the parent of a nested class VB.NET?

In general, according to the OOP paradigm, my understanding of encapsulation basically says:
If a member is private, it can only be accessed by the class.
If a member is protected, it can only be accessed by the base class and any derived classes.
If a member is public, it can be accessed by anyone.
If I have a nested class, can I declare a property to be accessible only to that class and the parent class it's nested within? For example:
Public Class ContainerClass
Public Class NestedClass
Protected myInt As Integer ' <- this is what I am wondering about '
Protected myDbl As Double ' <- this is what I am wondering about '
Sub New()
myInt = 1
myDbl = 1.0
End Sub
End Class
Private myNestedObject As New NestedClass
' this function is illegal '
Public Sub GrowNestedObject(ByVal multiplier As Integer)
myNestedObject.myInt *= multiplier
myNestedObject.myDbl *= multiplier
End Sub
End Class
In the example, I cannot directly access myNestedObject.myInt or myNestedObject.myDbl from an instance of ContainerClass if those members are Private or Protected. But suppose I don't want to make them Public, because then they are TOO exposed: they can be altered from anywhere, not just within a ContainerClass object. Declaring them Friend would still be too weak as that would allow them to be altered from anywhere within the application.
Is there any way to accomplish what I am going for here? If not, can anyone think of a more sensible way to achieve something like this?
There is no way of doing this directly with a combination of accessibility modifiers.
The best way I can think of doing this is as follows. It involves an extra level of indirection.
Create a Nested Interface with Private accessibility. This will give only the Parent class and nested children access
Add the fields you want access to to that interface
Make the Nested class implement the interface
Make all of the implementations have private accessibility
Now the parent class and only the parent class will have access to those properties and methods.
For Example:
Class Parent
Private Interface Interface1
ReadOnly Property Field1() As Integer
End Interface
Public Class Nested1
Implements Interface1
Private ReadOnly Property Field1() As Integer Implements Interface1.Field1
Get
Return 42
End Get
End Property
End Class
Sub New()
Dim child As Interface1 = New Nested1
Dim x = child.Field1
End Sub
End Class
Based on JaredPar's answer, you could use a Private ChildClass but a Public Interface that reveals only what it sould show :
Public Class ParentClass
Public Interface IChildClass
ReadOnly Property i() As Integer
Sub SomeSub()
End Interface
Private Class ChildClass
Implements IChildClass
Public myInt As Integer
Public ReadOnly Property i() As Integer Implements IChildClass.i
Get
Return myInt
End Get
End Property
Public Sub SomeSub() Implements IChildClass.SomeSub
End Sub
End Class
Public Shared Function GetNewChild() As IChildClass
Dim myChild = New ChildClass()
myChild.myInt = 3
Return myChild
End Function
End Class
Usage :
Dim c As ParentClass.IChildClass = ParentClass.GetNewChild()
MessageBox.Show(c.i)
c.i = 2 ' Does not compile !
c.SomeSub()