Consider the following example:
Public Class ParentClass
Public Sub GenerateReport
Dim Col As Collection
Col = GetItemCollection()
End Sub
Public Overridable Function GetItemCollection() As Collection
GetItemCollection = New Collection
GetItemCollection.Add("1")
GetItemCollection.Add("2")
GetItemCollection.Add("3")
End Function
End Class
Public Class ExtendedClass
Inherits ParentClass
Public Overrides Function GetItemCollection() As Collection
GetItemCollection = New Collection
GetItemCollection.Add("A")
GetItemCollection.Add("B")
GetItemCollection.Add("C")
End Function
End Class
Public Sub Main()
Dim cls As New ExtendedClass
cls.GenerateReport()
End Sub
When Main() calls cls.GenerateReport(), is the variable Col going to be a collection of numbers or letters? I'm hoping that it will recognize that cls is an instance of ExtendedClass and call the overridden method and return the letters.
It will be a collection of letters as you did override the method. However, where did you declare the GetItemCollection? You still need an instance variable.
Related
I searched over 20 articles and I am still slightly confused with inheritance. I have three classes as such:
Class A
Private _Mode As String
Public Function returnMode() As String
Return _Mode
End Function
Class B
Inherits Class A
Private _Mode As String = "modeb"
Class C
Inherits Class A
Private _Mode As String = "modec"
Now any time I create a B or C class, I would like the object to return the child class _Mode. I can make the New() function _Mode = "modeb" but I wanted to know a better way or more correct way.
How do I properly declare the variable _Mode?
One option would be to make _Mode Protected instead of Private so you can set it from the subclasses, and set the value is the subclass constructors:
Class A
Protected _Mode As String
Public Function returnMode() As String
Return _Mode
End Function
Class B
Inherits Class A
Public Sub New()
_Mode = "modeb"
End Sub
Class C
Inherits Class A
Public Sub New()
_Mode = "modec"
End Sub
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 ...
I would like to write a nested class into an existing class of my own. But I can't find how because I have no idea how this is really called.
What do I mean by nested class? With a table dt from the DataTable class, I can write dt.Columns.add(). Columns would be property of the main class and add would be a method from a nested class.
Any suggestions?
That is not a nested class, it's simply a class. The Columns property is of the type DataColumnCollection that has a public method called Add. To build your own in a similar fashion it would simply be:
Public Class MyFirstClass
Public Sub New()
End Sub
Dim _second As New MySecondClass()
Public Property Second() As MySecondClass
Get
Return _second
End Get
Set(ByVal Value As MySecondClass)
_second = Value
End Set
End Property
End Class
Public Class MySecondClass
Public Sub New()
End Sub
Public Sub MySecondClassMethod()
'Do something
End Sub
End Class
This would then be called in some other class or functionality like:
Dim x as New MyFirstClass()
x.Second.MySecondClassMethod()
For the problem I have these classes:
Public MustInherit Class BaseLeaf(Of T)
Implements IBaseLeaf
// etc
Public Class WebsiteLeaf
Inherits BaseLeaf(Of Headline)
// etc
Public Class WebsiteCollection
Inherits BaseCollection(Of WebsiteLeaf)
// etc
Public Class SubscriptionList
Private mCollection As BaseCollection(Of IBaseLeaf)
Public Sub LoadSubscriptions(ByVal collection As BaseCollection(Of IBaseLeaf))
mCollection = collection
End Sub
In the Main class I am trying to call the following function:
Private Sub FetchSubscriptions(ByVal websites As WebsiteCollection)
gUser.SubscriptionList.LoadSubscriptions(websites)
// code
End Sub
This will access LoadSubscriptions with passing the "websites" variable.
As you can see LoadSubscriptions expects a BaseCollection(Of IBaseLeaf).
The "websites" variable is a WebsiteCollection, which is a BaseCollection(Of WebsiteLeaf(Of Headline)).
Now I am getting the error: Value of type 'WebsiteCollection' cannot be converted to 'BaseCollection(Of IBaseLeaf)'.
What I am doing wrong here?
If class B is a descendent of class A this does not mean that Collection(Of B) is a descendant of Collection(Of A)!
If you have these definitions
Dim stringList As List(Of String)
Public Sub DoSomthingWithList(list As List(Of object))
list.Add(Date.Now)
End Sub
and you could call the method like this
DoSomthingWithList(stringList)
then the method would try to add a Date to the list which is actually a list of strings! Since the parameter is typed as object the date would be boxed (i.e. converted to an object) but not converted to string.
Therefore the collections List(Of X) and List(Of Y) are never compatible, even if Y inherits X.
Let's look at another example
Public Class TestClass
Implements IBaseLeaf
// etc
What happens if you call LoadSubscriptions with a WebsiteCollection?
Public Sub LoadSubscriptions(ByVal collection As BaseCollection(Of IBaseLeaf))
collection.Add(New TestClass())
End Sub
I have two classes:
class class2
inherits class1
public sub modify()
'modify property of class1
end sub
end class
How can I modify class1 in a sub in class2?
You just call it. Example:
Public Class class1
Private _Value As String = String.Empty
Property Value() As String
Get
Return _Value
End Get
Set(ByVal value As String)
_Value = value
End Set
End Property
End Class
Public Class class2
Inherits class1
Public Sub modify()
Value = "modified"
End Sub
End Class
And to show it works:
Dim c2 As New class2
c2.modify()
MessageBox.Show(c2.Value)
You are asking about properties, note that only protected and public properties are visible to inherited classes.
You need the MyBase keyword when you are overriding an existing function in the parent class. Other protected or public properties or functions can be accessed regulary without any special keyword.
One tip I wanted to add to the above comments regarding accessing base class info is where you have a base class without a default contructor or want to use a specific constructor This is a good opportunity to use Mybase. You have to call the constructor before any additional actions take place in this scenario.
Public Class MyClass
Inherits baseClass
Public Sub New()
mybase.new("Oranges")
End Sub
End Class
Public Class baseClass
Private _someVariable as String
Public Sub New(byval passedString as string)
_someVariable = passedString
End Sub
End Class