Incompatible interface - vb.net

Please see the code below:
Public Class clsCar
Implements IVehicle
Public Function getWheels() As Integer Implements IVehicle.getWheels
Return 4
End Function
End Class
Public Interface IVehicle
Function getWheels() As Integer
End Interface
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim list As List(Of IVehicle) = New List(Of IVehicle)
Dim v1 As IVehicle = New clsCar
Dim v2 As IVehicle = New clsBus
list.Add(v1)
list.Add(v2)
Dim IVehicle As IVehicle = New clsCar
Dim IVehicle2 As IVehicle = New clsBus
For Each IVehicle In list
MsgBox(IVehicle.getWheels())
Next
End Sub
End Class
I want to add a new function to the clsBus class:
Public Function getWheels(ByVal strCarType As String) As Integer
If strCarType = "Robin Ryliant" Then
Return 3
Else
Return 4
End If
End Function
How do I call this from the FOR EACH statement? At the moment it will call getWheels with no arguments.

You will have to add the method overload to the interface in order to be able to call it from a IVehicle variable.
Public Interface IVehicle
Function getWheels() As Integer
Function getWheels(ByVal strCarType As String) As Integer
End Interface
But probably it is better to have different, more specialized car types
Public Class clsCar
Implements IVehicle
Public Overridable Function getWheels() As Integer Implements IVehicle.getWheels
Return 4
End Function
End Class
Public Class clsRobinRyliantCar
Inherits clsCar
Public Overrides Function getWheels() As Integer
Return 3
End Function
End Class
This does not break the inheritance hierarchy and is purely polymorphic.

I think I would go for something more like this, with the number of wheels being an instance property (code in LINQPad format):
Sub Main
Dim list As List(Of IVehicle) = New List(Of IVehicle)()
list.Add(New clsCar("Ford Focus", 4))
list.Add(New clsCar("Robin Ryliant", 3))
list.Add(New clsBus())
For Each v In list
Console.WriteLine(String.Format("{0}:{1}", v.GetVehicleType(), v.GetWheels()))
Next
End Sub
' Define other methods and classes here
Public Interface IVehicle
Function GetVehicleType() As String
Function GetWheels() As Integer
End Interface
Public MustInherit Class clsVehicle
Implements IVehicle
Protected Property VehicleType As String
Protected Property Wheels As Integer
Protected Sub New(vehicleType As String, wheels As Integer)
Me.VehicleType = vehicleType
Me.Wheels = wheels
End Sub
Public Function GetVehicleType() As String Implements IVehicle.GetVehicleType
Return Me.VehicleType
End Function
Public Function GetWheels() As Integer Implements IVehicle.GetWheels
Return Me.Wheels
End Function
End Class
Public Class clsCar
Inherits clsVehicle
Public Sub New(vehicleType As String, wheels As Integer)
MyBase.New(vehicleType, wheels)
End Sub
End Class
Public Class clsBus
Inherits clsVehicle
Public Sub New()
MyBase.New("Bus", 4)
End Sub
End Class

If your clsBus and clsCar are meant to refer to a specific car then the type should be a member of that class already, not something you pass in when you want to get information. To this end I'd suggest that you have "type" as something you can pass in the constructor and then the method on the bus would have no parameters and would just refer to its internal type to determine how many wheels it has.
I'm not too fluent with VB.NET so would probably make mistakes in example code but hopefully you get what I mean. If not I'll knock up some code. :)

Related

Interface usage within three projects

I will try to simplify as possible. In my solution i got 3 separated projects:
Main - where i use Bal
Bal - business logic, eg. classes:
Artikel
Material
Dal - data layer logic, eg. classes:
DALArtikel
DALMaterial
Now Dal's classes implements interface IDAL which looks like follows:
Public Interface IDAL
Function isExist(name As String) As Boolean
Function GetIdByName(name As String) As Integer
Function GetNameById(pId As Integer) As String
End Interface
Then i can call interface's methods from Bal's project. Every BAL's class has it's DAL class like for Artikel is DALArtikel.
Now every BAL's classes inherits from one Base class which looks like below. This Base class implements interface similar to mentioned above called IGetInformation
Public Class Base
Implements IGetInformation
Property Id As Integer
Property DAL As DataLayer.IDAL
Protected Sub New()
End Sub
Protected Sub New(dal As DataLayer.IDAL)
Me.DAL = dal
End Sub
Protected Sub New(pId As Integer)
_Id = pId
End Sub
Public Overridable Function IsExist(name As String) As Boolean Implements IGetInformation.IsExist
Return DAL.isExist(name)
End Function
Public Overridable Function GetNameById(pId As Integer) As String Implements IGetInformation.GetNameById
Return DAL.GetNameById(pId)
End Function
Public Overridable Function GetIdByName(pName As String) As Integer Implements IGetInformation.GetIdByName
Return DAL.GetIdByName(pName)
End Function
Mentioned interface:
Public Interface IGetInformation
Function isExist(name As String) As Boolean
Function GetIdByName(name As String) As Integer
Function GetNameById(pId As Integer) As String
End Interface
So every Bal's class like Artikel is constructed as following:
Public Class Artikel
Inherits Base
Property Serie As String
Property Nummer As String
Property Name As String
Sub New()
MyBase.New(New DALArtikel)
End Sub
Sub New(pId As Integer)
MyBase.New(New DALArtikel)
Id = pId
End Sub
Sub New(pId As Integer, pSerie As String)
MyBase.New(New DALArtikel)
Id = pId
Serie = pSerie
End Sub
This way i can instatiate artikel class in Main project and call it's e.g isExist method without specyfing specific DAL class associated with it as in Artikel class constructor it was already specified. The problem is now when i want to add new method which will be not in IDAL interface i have to implement like this in Artikel:
Public Function IsExistBarcode(barcode As String) As Boolean
Return New DataLayer.DALArtikel().CheckIfBarcodeExist(barcode)
End Function
so this time i have to specify DALArtikel before i call CheckIfBarcodeExist as my property DAL doesn't know it.
Generally i don't like the way as it is currently, you see that i use two separate exactly the same content interfaces for bal's and dal's projects and the logic behind. Do you know other efficient way which i could change current logic to be let's say 'better'?
Appreciate possible improvment example according to my situation. Sorry for long post but couldn't make it more less. If something unclear let me know.

Implement same logic for diffrent objects as T

I suppose to use T but i am not sure how do it in proper way.
Let's consider following example.
Base class:
Public Class HtmlBase
Implements IGetInformation
Public Overridable Function IsExist() As Boolean Implements IGetInformation.IsExist
Throw New NotImplementedException()
End Function
Public Overridable Function GetIdByName(pName As String) As Integer Implements IGetInformation.GetIdByName
Throw New NotImplementedException()
End Function
End Class
Example classes which inherit from base class:
Public Class HtmlSubSection
Inherits HtmlBase
'--sometimes i have to overload to add additioinal parameter
Public Overloads Function isExist(subsection As String) As Boolean
Dim dlsubkategorie As New DataLayer.DALSubSection
Return dlsubkategorie.CheckIfSubSectionExist(subsection)
End Function
Public Overrides Function GetIdByName(subsectionName As String) As Integer
Dim dlget As New DataLayer.DALSubSection
Return dlget.GetSubSectionIdByName(subsectionName)
End Function
End Class
Public Class HtmlSection
Inherits HtmlBase
'sometime i have to overload to add additioinal parameter
Public Overloads Function IsExist(section As String) As Boolean
Dim dlsubkategorie As New DataLayer.DALSection
Return dlsubkategorie.CheckIfSectionExist(section)
End Function
Public Overrides Function GetIdByName(Name As String) As Integer
Dim dlsubkategorie As New DataLayer.DALSection
Return dlsubkategorie.GetSectionIdByName(Name)
End Function
End Class
As could be seen above two classes which inherits from base within their methods has same logic (sometimes i have to use additional parameter therefore overloads there, but are using diffrent DAL class to call. I would like to implement this logic in base class and for each just point to specific DAL. How to do that to not everytime in those classes write e.g:
Dim dlsubkategorie As New DataLayer.<DALSection>
Return dlsubkategorie.GetSectionIdByName(Name)
EDIT:
Htmlbase constructor's:
Sub New()
End Sub
Sub New(pId As Integer)
_Id = pId
End Sub
HtmlSubSection's constructors:
Sub New()
MyBase.New()
AvailableSentences = New List(Of HtmlSubSection_Sentence)
SelectedSentences = New List(Of HtmlSubSection_Sentence)
End Sub
Sub New(pId As Integer)
MyBase.New(pId)
End Sub
Sub New(pName As String)
_Name = pName
End Sub
Sub New(pId As Integer, pName As String)
MyBase.New(pId)
_Name = pName
End Sub
HtmlSection's constructors:
Sub New()
MyBase.New()
End Sub
Sub New(pId As Integer)
MyBase.New(pId)
End Sub
Sub New(pId As Integer, pName As String, pPosition As Integer)
MyBase.New(pId)
_Name = pName
_Position = pPosition
End Sub
Sub New(pName As String)
_Name = pName
End Sub
Sub New(pName As String, pPosition As Integer)
_Name = pName
_Position = pPosition
End Sub
You don´t need generic types here. Just use Interfaces, Sub Classing and Polymorphism correctly.
New Interface IDAL which is implemented by DAL classes to get rid of different method names which take same parameters and do the same:
Public Interface IDAL
Function CheckIfSectionExist(section As string) As Boolean
Function GetSectionIdByName(section As string) As Integer
End Interface
Public Class DALSection
Implements IDAL
Public Function CheckIfSectionExist(section As string) As Boolean Implements IDAL.CheckIfSectionExist
...
End Function
Public Function GetSectionIdByName(section As String) As Integer Implements IDAL.GetSectionIdByName
...
End Function
End Class
Public Class DALSubSection
Implements IDAL
Public Function CheckIfSubSectionExist(subSection As string) As Boolean Implements IDAL.CheckIfSectionExist
...
End Function
Public Function GetSubSectionIdByName(subSection As String) As Integer Implements IDAL.GetSectionIdByName
...
End Function
End Class
Base class changed to abstract and the constructor now takes IDAL parameter. Function can now be executed polymorphic. Added a isExists(string) function to avoid overloading:
Public MustInherit Class HtmlBase
Implements IGetInformation
Public Property DAL as DataLayer.IDAL
Protected Sub New(dal as DataLayer.IDAL)
Me.DAL = dal
End Sub
Public Overridable Function isExist() As Boolean Implements IGetInformation.isExist
Return True
End Function
Public Overridable Function isExist(section As String) As Boolean
Return DAL.CheckIfSectionExist(Section)
End Function
Public Overridable Function GetIdByName(pName As String) As Integer Implements IGetInformation.GetIdByName
Return DAL.GetSectionIdByName(pName)
End Function
End Class
Client classes only need to give correct DAL to base class:
Public Class HtmlSubSection
Inherits HtmlBase
Public Sub New()
MyBase.New(New DataLayer.DALSubSection)
End Sub
End Class
Public Class HtmlSection
Inherits HtmlBase
Public Sub New()
MyBase.New(New DataLayer.DALSection)
End Sub
End Class
Basically it would be ideal if IGetInformation had a isExist method with an optional string parameter. This would save one unneccessary method in HtmlBase.

VB generics with constraints -- type casting and inheritance?

Take this scenario:
Public Interface IMyClass
End Interface
Public mustinherit class MyBaseClass : implements IMyClass
End Class
public class MyClass : inherits MyBaseClass
End Class
public class MyModel(of t as IMyClass)
private Dim _parameter as t
Public Sub New(byval parameter As t)
_parameter As t
End Sub
End class
In my controller, I can do this with no problem:
Dim _myclass as IMyClass = new MyClass()
Can I do something similar with this:
Dim _myModel as MyModel(of IMyClass) = new MyModel(of MyClass)
???
My initial thought was wrong, as I thought the conversion could be done automatically, but it appears it is not done. Any way to achieve the same thing within .NET?
EDIT
I updated the MyModel class to show more of what I was doing. I want to constrain the instance I create, but then do what would be a narrowing conversion with traditional, non-generics code. Basically, my partial Razor views would require the explicit model, and those views end up rendering another view that will take that model and display it. Because the models all implement or inherit a class that implements IMyClass, all the methods should exist on all of the instances and should be callable but the types are not interchangable.
Let’s modify MyModel slightly, shall we?
Public Class MyModel(Of T As IMyClass)
Private _parameter As T
Public Sub Something(parameter As T)
_parameter = parameter
End Sub
End class
Public Class MyClassA : Inherits MyBaseClass
End Class
Public Class MyClassB : Inherits MyBaseClass
End Class
Dim _myModel As MyModel(Of IMyClass) = New MyModel(Of MyClassA)()
_myModel.Something(New MyClassB()) ' Boom!
If the assignment were allowed the last line would pose a problem: MyMode(Of MyClassA)._parameter has type MyClassA but the last line would assign an object of the (unrelated) type MyClassB. This is illegal and so VB forbids it.
Do you need multiple varieties of MyModel, or are you just attempting to require that the stored object be constrained to IMyClass?
Simplest approach (that might not do everything you need):
Public Interface IMyClass
Sub DoIt()
End Interface
Public Class MyModel
Private ReadOnly _parameter As IMyClass
Public Sub New(parameter As IMyClass)
_parameter = parameter
End Sub
Public Sub DoItToIt()
_parameter.DoIt()
End Sub
End Class
Public Class MyClassA
Implements IMyClass
Public Sub DoIt() Implements IMyClass.DoIt
End Sub
End Class
Public Class Tests
Public Sub Main()
Dim model1 As MyModel = New MyModel(New MyClassA)
model1.DoItToIt()
End Sub
End Class
Next step up in complexity is to define an interface IHasMyClass for classes that contain an IMyClass. This supports manipulations based on the allowed type, and the actual type, of the contained object:
Public Interface IMyClass
Sub DoIt()
End Interface
Public Interface IHasMyClass
Function GetIt() As IMyClass
Function GetItsType() As Type
Function GetAllowedType() As Type
End Interface
Public Class MyModel(Of T As IMyClass)
Implements IHasMyClass
Private ReadOnly _parameter As IMyClass
Public Sub New(parameter As IMyClass)
_parameter = parameter
End Sub
Public Sub DoItToIt()
_parameter.DoIt()
End Sub
Public Function GetItAsT() As T
Return _parameter
End Function
Public Function GetIt() As IMyClass Implements IHasMyClass.GetIt
Return _parameter
End Function
Public Function GetItsType() As Type Implements IHasMyClass.GetItsType
Return _parameter.GetType()
End Function
Public Function GetAllowedType() As Type Implements IHasMyClass.GetAllowedType
Return GetType(T)
End Function
End Class
Public Class MyClassA
Implements IMyClass
Public Sub DoIt() Implements IMyClass.DoIt
End Sub
End Class
Public Class Tests
Public Sub Main()
' Allow any IMyClass
Dim model1 As MyModel(Of IMyClass) = New MyModel(Of IMyClass)(New MyClassA)
model1.DoItToIt()
Dim it As IMyClass = model1.GetIt()
Dim allowedT As Type = model1.GetAllowedType()
' Restrict to MyClassA
Dim modelA As MyModel(Of MyClassA) = New MyModel(Of MyClassA)(New MyClassA)
modelA.DoItToIt()
Dim itA1 As IMyClass = modelA.GetIt()
Dim itA2 As MyClassA = modelA.GetItAsT()
Dim allowedTA As Type = modelA.GetAllowedType()
End Sub
End Class
In Tests(), notice that we now need to declare whether we are creating a MyModel that accepts ANY IMyClass MyModel(Of IMyClass), or one that requires a specific sub-class MyModel(Of MyClassA).
If we want to manipulate MyModels, that may be either of the above types, we use the common interface:
Dim model As IHasMyClass
model = model1
...
model = modelA
Or in your case, to support all the functionality of MyModel, rename IHasMyClass as IMyModel, and add the various MyModel functions, but instead of T, use IMyClass:
Public Interface IMyModel
Function GetIt() As IMyClass
Function GetItsType() As Type
Function GetAllowedType() As Type
Sub DoItToIt()
Function CompareIt(other As IMyClass) As Integer
End Interface
And make appropriate changes/additions to IMyClass and MyModel.
Then it becomes possible to do:
Dim model As IMyModel = modelA
If model.CompareIt(model1.GetIt()) > 0 ...

A class can only be a template for a single object not a template for a collection

I have a simple class List.vb which is the following:
Public Class List
Public fList As List(Of Integer)
Public Sub New()
fList = New List(Of Integer)
fList.Add(1)
fList.Add(2)
fList.Add(3)
fList.Add(4)
fList.Add(5)
End Sub
End Class
The Console application is using this class like the following:
Module Module1
Sub Main()
Dim fObject As List = New List
Dim cnt As Integer = 0
For Each x As Integer In fObject.fList
Console.WriteLine("hello; {0}", fObject.fList.Item(cnt).ToString())
cnt = cnt + 1
Next
Console.WriteLine("press [enter] to exit")
Console.Read()
End Sub
End Module
Can I change the class code so that List.vb is a list(of integer) type?
This would mean that in the Console code I could replace In fObject.fList with just In fObject?
Or am I barking up the wrong tree - should classes be single objects and lists should be collections of classes ?
Yes, you can do that. In order for an object to be compatible with For Each, it must have a GetEnumerator function:
Public Function GetEnumerator() As IEnumerator _
Implements IEnumerable.GetEnumerator
Return New IntListEnum(fList)
End Function
The IntListEnum class must, in turn, implement IEnumerator, like this:
Public Class IntListEnum Implements IEnumerator
Private listInt As List(Of Integer)
Dim position As Integer = -1
Public Sub New(ByVal fList As List(Of Integer))
listInt = fList
End Sub
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
position = position + 1
Return (position < listInt.Count)
End Function
Public Sub Reset() Implements IEnumerator.Reset
position = -1
End Sub
Public ReadOnly Property Current() As Object Implements IEnumerator.Current
Get
Try
Return listInt(position)
Catch ex As IndexOutOfRangeException
Throw New InvalidOperationException()
End Try
End Get
End Property
End Class
Now you can make fList private, and iterate your List as follows:
For Each x As Integer In fObject
You can see a complete example here.
The answer that dasblinkenlight has provided is excellent, but if all you need is a list that of integers that is pre-populated, you can just inherit from List(Of Integer) and then have the class populate itself in the constructor:
Public Class List
Inherits List(Of Integer)
Public Sub New()
Add(1)
Add(2)
Add(3)
Add(4)
Add(5)
End Sub
End Class
When you inherit from List(Of Integer), your class automatically gets all of the functionality implemented by that type, so your class also becomes a list class that works the same way. Then, you can just use it like this:
Dim fObject As New List()
For Each x As Integer In fObject
Console.WriteLine("hello; {0}", x)
Next

Organizing VB.Net Mehods

Say I have a class with several methods within it. I want to organize the methods into groupings that can be accessed without constructing a new object each time. The purpose is to group the methods of the class into logical buckets
For instance:
Dim myclass as MyCustomClass
myclass.Shipping.Get_List()
myclass.Production.Get_List()
What is the best way to do this? I tried nested classes, but VB.NET won't let me access the methods as shown above.
so this is how i would do what you want
this is not the best design of the world but it would work
I would suggest you to move the actual get_list and other kind of method / property into the specific class while keeping the common one in the parent class, which in this case is test
but then, I have no idea what your code look like so from that point on, it's your choice
Module Module1
Sub Main()
Dim test As New test
test.Production.Get_List()
test.Shipping.Get_List()
End Sub
End Module
Public Class Shipping
Private parent As test
Public Sub New(ByRef parent As test)
Me.parent = parent
End Sub
Public Function Get_List() As List(Of Integer)
Return parent.GetShipping_List
End Function
End Class
Public Class Production
Private parent As test
Public Sub New(ByRef parent As test)
Me.parent = parent
End Sub
Public Function Get_List() As List(Of Integer)
Return parent.GetProduction_List
End Function
End Class
Public Class test
Public Property Production As Production
Public Property Shipping As Shipping
Public Function GetShipping_List() As List(Of Integer)
Return Nothing
End Function
Public Function GetProduction_List() As List(Of Integer)
Return Nothing
End Function
Public Sub New()
Production = New Production(Me)
Shipping = New Shipping(Me)
End Sub
End Class
With caution that you more than likely should re-evaluate your architecture, you could implement your pattern like this:
Public Class MyCustomClass
Private _shippingList As List(Of String)
Private _productionList As List(Of String)
Public Production As ProductionClass
Public Shipping As ShippingClass
Public Sub New()
Production = New ProductionClass(Me)
Shipping = New ShippingClass(Me)
End Sub
Public Class ShippingClass
Private _owner As MyCustomClass
Public Sub New(owner As MyCustomClass)
_owner = owner
End Sub
Public Function Get_List()
Return _owner._productionList
End Function
End Class
Public Class ProductionClass
Private _owner As MyCustomClass
Public Sub New(owner As MyCustomClass)
_owner = owner
End Sub
Public Function Get_List()
Return _owner._productionList
End Function
End Class
End Class
However, if your true intent is simply organizing the methods in a more accessible and logical manner, I would suggest considering:
Public Class MyCustomClass
Public Sub ShippingListGet()
End Sub
Public Sub ShippingListAddTo()
End Sub
Public Sub ShippingThatDO()
End Sub
Public Sub ShippingThisDo()
End Sub
Public Sub ProductionListGet()
End Sub
Public Sub ProductionListAddTo()
End Sub
Public Sub ProductionThisDo()
End Sub
Public Sub ProductionThatDo()
End Sub
End Class
Keep in mind, some people consider that difficult to read. I personally prefer organization along those lines so when the methods are sorted alphabetically they group logically.
I have found the solution I was looking for using interfaces
Public Interface ICompany
Function Company_List() As DataTable
End Interface
Public Class MainClass
Public Company As ICompany = New CompanyClass
Public Sub New()
MyBase.New()
End Sub
Private Class CompanyClass
Public Sub New()
MyBase.New()
End Sub
Public Function Company_List() As DataTable
My code....
End Function
End Class
End Class