I have a situation in VB.Net where I have a variable that will be an instance of one of two classes, both derived from a parent class, but which class is determined at run time. To do this, I declare the variable as the parent class, then set it to one or the other child class based on a true/false value.
After that, I invoke the only public method (Main) for the child class, I want the parameter it takes be different based on which child class it is. However, I'm finding that I can't do this with an override or overload, at least as I understand them. Is there a way to do this?
I guess I could have Main1 and Main2 as inherited methods with the specific parameter type and invoke them conditionally as well, but just looking to see if I can keep it simple.
Here's a mock-up of what I'm trying to accomplish, which doesn't work:
Public Class ThisParam
End Class
Public Class Param1
Inherits ThisParam
End Class
Public Class Param2
Inherits ThisParam
End Class
Public Class ThisBase
Public Overridable Sub Main (X as ThisParam)
'Empty for inheritance
End Sub
End Class
Public Class Child1
Inherits ThisBase
Public Overrides Sub Main(X as Param1)
'Do Stuff
End Sub
End Class
Public Class Child2
Inherits ThisBase
Public Overrides Sub Main(X as Param2)
'Do Stuff
End Sub
End Class
Dim MyObject As ThisBase
Dim MyParam as ThisParam
If True then MyObject = New Child1 Else MyObject = New Child2 End If
If True then MyParam = New Param1 Else MyParam = New Param2 End If
MyObject.Main(MyParam)
Related
I have a little problem understanding what's wrong here.
I have code similiar to this one
Public Class Parent
Public name As String = "dad"
Public Function sayname() As String
Return name
End Function
End Class
Public Class child
Inherits Parent
Shadows name As String = "son"
End Class
When I do this:
dim littleson as new child
littleson.sayname()
it will return "dad", I want it to return "son". What's wrong with what I do?
Don't shadow it, just set the value in the constructor.
Public Class Child
Inherits Parent
Public Sub New()
MyBase.New()
name = "son"
End Sub
End Class
Shadows creates a new variable completely different from the one in the parent.
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()
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
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()
I have the following sample code in a VB.NET console application. It compiles and works, but feels like a hack. Is there a way to define EmptyChild so that it inherits from Intermediate(Of T As Class) without using the dummy EmptyClass?
Module Module1
Sub Main()
Dim Child1 = New RealChild()
Child1.Content = New RealClass()
Dim Child2 = New EmptyChild()
Console.WriteLine("RealChild says: " & Child1.Test)
Console.WriteLine("EmptyChild says: " & Child2.Test)
Console.ReadLine()
End Sub
Public Class EmptyClass
End Class
Public Class RealClass
Public Overrides Function ToString() As String
Return "This is the RealClass"
End Function
End Class
Public MustInherit Class Base(Of T As Class)
Private _content As T = Nothing
Public Property Content() As T
Get
Return _content
End Get
Set(ByVal value As T)
_content = value
End Set
End Property
Public Overridable Function Test() As String
If Me._content IsNot Nothing Then
Return Me._content.ToString
Else
Return "Content not initialized."
End If
End Function
End Class
Public MustInherit Class Intermediate(Of T As Class)
Inherits Base(Of T)
'some methods/properties here needed by Child classes
End Class
Public Class RealChild
Inherits Intermediate(Of RealClass)
'This class needs all functionality from Intermediate.
End Class
Public Class EmptyChild
Inherits Intermediate(Of EmptyClass)
'This class needs some functionality from Intermediate,
' but not the Content as T property.
Public Overrides Function Test() As String
Return "We don't care about Content property or Type T here."
End Function
End Class
End Module
The other way to do this would be to move the generic code out of the Base class and then create 2 Intermediate classes like this:
Public MustInherit Class Intermediate
Inherits Base
'some methods/properties here needed by Child classes
End Class
Public MustInherit Class Intermediate(Of T As Class)
Inherits Intermediate
'implement generic Content property here
End Class
Then RealChild would inherit from the generic Intermediate and EmptyChild would inherit from the non-generic Intermediate. My problem with that solution is that the Base class is in a separate assembly and I need to keep the code that handles the generic type in that assembly. And there is functionality in the Intermediate class that does not belong in the assembly with the Base class.
Yes, you need to specify a type parameter when you inherit, or your EmptyChild must be generic as well. But, you don't have to dummy up a EmptyClass - just use Object as your type parameter:
Public Class EmptyClass
Inherits Intermediate(Of Object)
End Class