I got an object(myObject) type Object. myObject inherits of another class that contain a fonction (ImyFunction). I want to call the function, but my project need to be in "Option Strict On". So it ask for declaration of the object.
Public MustInherit Class IClass(Of T1)
...
Public Sub IMyFunction()
...
Public Class myClass1 : Inherits IClass(Of Item1)
...
Public Class myClass2 : Inherits IClass(Of Item2)
dim obj as object = new myClass1
...
obj.IMyFunction 'at this moment, I dont know whish class base of IClass I have
(its just a sample)
I cant do obj.IMyFunction because of the strict option.
Maybe there's a cast way?
The MustInherit keyword does not mean that you cannot use it as a variable type, it just means that you cannot instantiate it. For instance:
Dim obj As IClass(Of Item1) = New myClass1() ' This works
Dim obj2 As IClass(Of Item1) = New IClass(Of Item1)() ' This will not compile
However since, it's generic, you have to specify the type of T1, so there's no way to do what I think it is that you really want to do:
Dim obj As IClass = New myClass1() ' Can't do this
obj.iMyFunction()
What I would recommend, in this case, would be to make either a non-generic base class or interface, like this:
Public Interface IInterface
Sub IMyFunction()
End Interface
Public MustInherit Class IClass(Of T1)
Implements IInterface
End Class
Then, you could do something like this:
Dim obj As IInterface = New myClass1()
obj.IMyFunction()
Related
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.
Lets say I have this class
Public Class Base(Of T)
Public SomeField as T
End Class
and now I want to inherit it in another class that would also be template but a little different
Public Class LittleDifferent : Inherits Base
Public SomeOtherField as T
End Class
So now if I wanted, I could make an object like this
Dim derp as New LittleDifferent(of Integer)
Obviously the code provided is broken since I don't know the correct syntax. How can I achieve this?
You just need to make the subclass generic as well:
Public Class LittleDifferent(Of T)
Inherits Base(Of T)
Public SomeOtherField as T
End Class
PS: Please try to avoid public fields.
I am currently working in Visual Studio 2013 with VB on .NET 4.5. I have an abstract base class which holds a collection of another abstract base class, like this:
Generic Base Class:
Public MustInherit Class CustomCollection(Of collectionItemType As CollectionItemBase)
Inherits Collections.ObjectModel.KeyedCollection(Of String, CollectionItemBase)
'...
End Class
Base Class Referened by Generic Base Class:
Public MustInherit Class CollectionItemBase
'...
End Class
I have a group of classes that inherit the generic base class "CustomCollection":
Public Class Collection1
Inherits CustomCollection(Of ClassThatDerivesFromCollectionItemBase1)
'...
End Class
Public Class Collection2
Inherits CustomCollection(Of ClassThatDerivesFromCollectionItemBase2)
'...
End Class
'etc...
This is the code I am using to try and convert an instance of Collection1 to a CustomCollection(Of CollectionItemBase):
'...
someProperty = instanceOfCollection1.Cast(Of CustomCollection(Of CollectionItemBase))
'...
This generates the following error at runtime, which to me seems to be nonsense:
"Unable to cast object of type
'd__b1`1[ApplicationName.CustomCollection`1[ApplicationName.CollectionItemBase]]'
to type
'ApplicationName.CustomCollection`1[ApplicationName.CollectionItemBase]'."
It appears to be claiming that it is unable to cast the object to its own type. Any thoughts?
When you use Cast(Of T) on an IEnumerable(Of U) it will cast every individual element to the destination type, so you should not pass the type of IEnumerable(Of T), but T itself.
In your case write your cast as
someProperty = instanceOfCollection1.Cast(Of CollectionItemBase)
This cast returns an IEnumerable(Of CollectionItemBase) that you can use.
But I don't think that was your question. Let's put that single line of code aside and talk about your question. The fact is generics don't work that way. Generic types Of Base/Derived types are totally different types.
In the simplest example, an instance of A(Of T) can't be cast to A(of U) even if T Inherits From U, because A(Of U) is a different type than `A(Of U)..
To replace class names with your real classes: an instance of
Collection1
or say
CustomCollection(Of ClassThatDerivesFromCollectionItemBase1)
can't be cast to
CustomCollection(Of CollectionItemBase)
despite of the fact that
ClassThatDerivesFromCollectionItemBase1
Inherits CollectionItemBase
because
CustomCollection(Of ClassThatDerivesFromCollectionItemBase1)
is a different type than
CustomCollection(Of CollectionItemBase).
This has nothing to do with covariance because (from MSDN):
In the .NET Framework 4, variant type parameters are restricted to
generic interface and generic delegate types.
So it won't work foe classes but works for interfaces. Let me make some changes to your code:
Public Class CollectionItemBase
End Class
Public Class ClassThatDerivesFromCollectionItemBase1
Inherits CollectionItemBase
End Class
Public Class ClassThatDerivesFromCollectionItemBase2
Inherits CollectionItemBase
End Class
Public Interface ICustomCollection(Of Out collectionItemType As CollectionItemBase)
End Interface
Public Class Collection1
Implements ICustomCollection(Of ClassThatDerivesFromCollectionItemBase1)
End Class
The Out modifier in this line
Public Interface ICustomCollection(Of Out collectionItemType As CollectionItemBase)
makes the type parameter covariant, meaning that if you have
Dim instanceOfCollection1 As New Collection1
these two lines will work:
Dim x As ICustomCollection(Of CollectionItemBase) = instanceOfCollection1
Dim y As ICustomCollection(Of Item1) = instanceOfCollection1
Hope that was helpful
I am trying to implement a mySubClass.vb file as a nested subclass of another main class. It seems like the Partial Class idea is what I need but the implementation isn't working when I try to pull mySubClass.vb in as a nested subclass of another main class.
My original implementation of this code used mySubClass directly so I know the functionality works. I just want to use mySubClass as a data structure within clsMain.
Main Class
Public Class clsMain
Public Property myIntProp as Integer
Public property myStrProp as String
'other properties
Partial Public Class MySubClass
'I want this functionality to be accessible via clsMain.MySubClass
'Just like any other property or function of clsMain
'Partial would keep things organized nicely
End Class
End Class
Sub Class
The class.vb that I want to use as clsMain.MySubClass.
File: MySubClass.vb
Partial Public Class MySubClass
Inherits BaseCollection
Private Class MySubSubClass '(Used for custom properties and functions)
'More properties and Functions
End Class
End Sub
Public Class BaseCollection 'functionality of MySubClass
Public Function MyFunction1()
'Return Data
End Function
End Class
How Main Class is Used
Public Class UsageClass
Private myMainDataStructure as new clsMain
Private Sub GetSubClassList()
dim MyData as ArrayList = myMainDataStructure.MySubClass.MyFunction1()
'^^^ error on this line: MyFunction1() is not a member of project.clsMain.MySubClass^^^
End Sub
End Class
Instead of trying to make this a Partial Class, you should just make a Property containing an instance of that class.
Nested classes must be created and have instances, just like top level classes. By making a property within your main class, you can automatically create that instance in your main class constructor, and your code will work as expected.
Public Class clsMain
Public Property myIntProp as Integer
Public property myStrProp as String
'other properties
Public Property OtherFunctionality as MyOtherClass = New MyOtherClass()
Then just define the class in a separate file:
Public Class MyOtherClass
Public Sub MyFunction1()
I have BaseAbstractClass(of T as WebControl) (VB Generics) which inherits WebControl.
BaseAbstractClass is inherited by ConcreteWrapper1, ConcreteWrapper2, and lastly, to shake things up a bit, ConcreteWrapper4. Each of these would inherit BaseAbstractClass using a different class inherited from WebControl.
What I would like to do is have factory that returns a ConcreteWrapper as a BaseAbstractClass(of WebControl). But whenever I try to return a new instance of a ConcreteWrapper I get a compile time conversion error.
[Edit: Code Added]
BaseAbstractClass
Public MustInherit Class BaseAbstractClass(Of T As WebControl)
Inherits WebControl
Protected _item As T
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
_item.RenderControl(writer)
End Sub
End Class
The other ConcreteWrappers look like this except with different CustomControl
Public Class ConcreteWrapper1
Inherits BaseAbstractClass(Of CustomControlInheritedFromWebControl1)
Public Sub New(ByVal control As CustomControlInheritedFromWebControl1)
MyBase._item = control
End Sub
End Class
Public Class CustomControlInheritedFromWebControl1
Inherits WebControl
//not the correct comment markers but the coloring works better
//do stuff here... Implm not important.
End Class
My Factory
Public Class WebControlFactory
Public Shared Function GetWebControl() As BaseAbstractClass(Of WebControl)
Return New ConcreteWrapper1(New CustomControlInheritedFromWebControl1())
End Function
End Class
[/Edit]
Could I get an explanation of what's going on and why that won't work (and possibly, a solution)?
Thanks!
ConcreteWrapper1 does not inherit from BaseAbstractClass(of WebControl), instead it inherits from BaseAbstractClass(of T)
BAC(of WebControl) is not interchangable with BAC(of T).
If you must use inheritence, you need two levels of abstraction.
WebControl
BAC inherits WebControl
BAC(of T) inherits BAC
Wrapper1 inherits BAC(of int)
Wrapper2 inherits BAC(of string)
Wrapper3 inherits BAC(of Foo)
Wrapper4 inherits BAC(of Bar)
Then you may return all instances of your Wrappers as BAC.
The reason is phrased well by Zooba:
You cannot cast between generic types with different type parameters. Specialized generic types don't form part of the same inheritance tree and so are unrelated types.