-
Nov 30th, 2022, 05:29 PM
#1
Thread Starter
Junior Member
Noob help with "nesting" classes!
Hi All,
I have a strong VBA background and am trying to break into the depths of .NET! Bear with me as I struggle to solve this issue!
I am trying to nest classes. Any child (or shall we... grandchild) class must be able to access any of it's parents (.... or grandparents) INSTANCE's properties.
A child/grandchild is useless without it's parents, and therefore should not be allowed to be called discretely.
I know this is asked a lot and i've sifted through the interwebs, just seems like there are many ways to skin this cat and i'm not sure what is the best for my scenario....
Here is what I have as a 'mock up'.
Code:
Class App
Public ReadOnly Property AppName As String
Get
AppName = "Test Application"
End Get
End Property
Public Class Database
Dim DatabaseName As String = "Test Application Database"
Public Sub PrintAppName()
Console.WriteLine("APP NAME IS: " & AppName)
End Sub
Public Class Functions
Public Shared Sub PrintDatabaseName()
Console.WriteLine("DB NAME IS: " & DatabaseName)
End Sub
End Class
End Class
End Class
Sub Main()
Dim a As New App
'want to use like this!
a.Database.PrintAppName()
a.Database.Functions.PrintDatabaseName()
End Sub
Thank you for your time!
-
Nov 30th, 2022, 07:36 PM
#2
Re: Noob help with "nesting" classes!
You seem confused about the difference between a type and an object. The fact that a class is declared inside another class says nothing about objects of those two types. You can create an instance of the outer class but that doesn't mean that an instance of the inner class automatically exists and vice versa.
-
Nov 30th, 2022, 07:40 PM
#3
Re: Noob help with "nesting" classes!
As examples, the ListViewSubItem class is nested inside the ListViewItem class but you can still create an instance of the former without creating an instance of the latter. You can't really use it in any meaningful way but there's no specific relationship between their existence. Conversely, the DataRow class is not nested within the DataTable class, yet the only way to create a DataRow is via a DataTable. An object accessing properties of another object requires a relationship between the objects, not just between the types.
-
Nov 30th, 2022, 09:46 PM
#4
Thread Starter
Junior Member
Re: Noob help with "nesting" classes!
Hi,
Thanks for your reply. I follow to a degree. But I am not following in full.
So, if this "requires a relationship between the objects", could you explain how to ties these classes together?
Below i've attempted to solve this by creating an instance of the child object at the constructor of the parent class.
But the code below does not work. If someone could offer a code example of how 'nesting' classes is done, then I think it would help me tie the pieces together.
Thanks
Edit: To further the confusion I have, this post does a wonderful job explaining my exact mindset:
http://https://stackoverflow.com/que...-another-class
Code:
Class App
Public ReadOnly Property AppName As String
Get
AppName = "Test Application"
End Get
End Property
Public Sub New()
'initilize a database object
Dim vDatabase As New Database
End Sub
Public ReadOnly Property GetDatabase As Database
Get
GetDatabase = vDatabase
End Get
End Property
'child class:
Public Class Database
Dim DatabaseName As String = "Test Application Database"
Public Sub PrintAppName()
Console.WriteLine("APP NAME IS: " & AppName)
End Sub
End Class
End Class
Sub Main()
Dim a As New App
a.GetDatabase.PrintAppName()
End Sub
End Module
Last edited by BitFlipper88; Nov 30th, 2022 at 10:04 PM.
-
Nov 30th, 2022, 10:39 PM
#5
Re: Noob help with "nesting" classes!
Crash course time. OOP is intended to mimic the way objects work in the real world, so you just have to look at real-world objects and how we deal with them to get a decent understanding of OOP.
When we look around at physical objects, we classify them, e.g. that's a building, that's a car, that's a tree, that's an animal. We all understand what those things are because we understand the description of what an object of that type has and what it does. It is from this classification that we derive the word "class" used in OOP. A class is a description of what a type of thing has and what it does. As in the real world though, we need instances of a type in order to actually do anything. You know what a car is, what it has and what it does, but you need a car object to actually drive anywhere. Every car has a colour but each car can have a different colour. All cars have doors but each car can have a different number of doors. Etc, etc. It's the same in the real world and in OOP.
You ask how to nest classes and the answer is to declare one inside the other. That's it, that's all. E.g.
vb.net Code:
Public Class Parent
Public Class Child
End Class
End Class
That's all there is to nested classes. If your actual problem is how to access the members of a Parent object from a Child object then that has nothing to do with nesting. In order for a Child object to access the properties of a Parent object, it must have a reference to a Parent object. That would be done the same way whether or not one class is nested within the other. The Child class would have to have a field/property of type Parent that you assign a Parent object to. Any Child object can then access the members of the Parent object assigned to that field/property. E.g.
vb.net Code:
Public Class Parent
Public Property Text As String
End Class
Public Class Child
Public Property Parent As Parent
Public Sub SetParentText(text As String)
If Parent IsNot Nothing Then
Parent.Text = text
End If
End Sub
End Class
vb.net Code:
Dim p As New Parent
Dim c As New Child
c.Parent = p
c.SetParentText("Hello World")
You can do that same thing whether or not the classes are nested. The details of how you maintain the relationship could vary, so it's up to you to make it work the way you want. For instance, you might implement it such that if a Parent refers to a specific Child then that Child also refers to that specific Parent and no other Child refers to it and vice versa. E.g.
vb.net Code:
Public Class Parent
Private _child As Child
Public Property Child As Child
Get
Return _child
End Get
Set(value As Child)
If value Is Nothing Then
If _child IsNot Nothing Then
Dim oldChild = _child
_child = Nothing
oldChild.Parent = Nothing
End If
ElseIf value IsNot _child Then
Dim oldChild = _child
_child = Nothing
oldChild.Parent = Nothing
_child = value
_child.Parent = Me
End If
End Set
End Property
End Class
Public Class Child
Private _parent As Parent
Public Property Parent As Parent
Get
Return _parent
End Get
Set(value As Parent)
If value Is Nothing Then
If _parent IsNot Nothing Then
Dim oldParent = _parent
_parent = Nothing
oldParent.Child = Nothing
End If
ElseIf value IsNot _parent Then
Dim oldParent = _parent
_parent = Nothing
oldParent.Child = Nothing
_parent = value
_parent.Child = Me
End If
End Set
End Property
End Class
I haven't tested that but I believe that it should do the job.
Again, if what you actually want is for a Child to not be able to be created except via a Parent then nesting classes won't do that. You would have to do what I already told you and define those classes in their own assembly (library) without any public means to create a Child directly. E.g.
vb.net Code:
Public Class Parent
Public Function NewChild() As Child
Return New Child(Me)
End Function
End Class
Public Class Child
Public ReadOnly Property Parent As Parent
Friend Sub New(parent As Parent)
Me.Parent = parent
End Sub
End Class
Because they are in the same assembly, the Parent class can access the Child class constructor declared Friend but any code outside that assembly cannot, thus the Public NewChild method is the only way to create a new Child object and it will automatically have a reference to the Parent that created it. That's basically how the DataTable and DataRow classes work.
-
Nov 30th, 2022, 10:39 PM
#6
Thread Starter
Junior Member
Re: Noob help with "nesting" classes!
Update:
So I played around some more and was able to essentially solve my problem.
Code:
Module Module4
'AN EXAMPLE OF NESTED CLASSES....
Class MainClass
Private Shared MainVar As String = "Main!" 'MUST BE SHARED FOR CHILD CLASS TO ACCESS
Public Child As ChildClass
Sub New()
Child = New ChildClass
End Sub
Class ChildClass
Public Sub DoSomething()
MsgBox("Hello " & MainVar) 'mainvar must be 'SHARED'
End Sub
Public Sub DoSomething2()
MsgBox("Do Something 2 " & MainVar)
End Sub
End Class
End Class
Sub Main()
Dim m As New MainClass
Dim c As New MainClass.ChildClass
c.DoSomething2()
m.Child.DoSomething()
End Sub
End Module
-
Nov 30th, 2022, 10:47 PM
#7
Re: Noob help with "nesting" classes!
Is that a solution though? A Sahred member is one that belongs to the class, rather than each instance of the class, so there will only be one MainVar value, no matter how many MainClass instances you create. Maybe you only intend to create one instance but this is still a bit of a hack.
Also, why are you declaring MainClass inside Module1? Even if you're going to ignore advice and nest one class inside another, there's no justification for nesting the outer class inside a module.
-
Dec 1st, 2022, 10:17 AM
#8
Re: Noob help with "nesting" classes!
The module might be a holdover from VBA. I think everything was in modules in VBA, though it's been many years since I've worked in VBA.
A module in .NET is essentially a class with all Shared members. It's a fig leaf added to make VB.NET act more like VB6, which was based on VBA syntax, as well as earlier versions of VB. Modules have their place in VB.NET, but they are fairly rare. I use them if I have global variables. Since global variables are, themselves, fairly problematic, they are usually not the right way to go, so I rarely use modules, and never more than one.
A class should be in it's own file, or files. If you want a nested class, it might be nicest to put it in a different file. That might be going a bit far, but a single class can be spread across multiple files, as you can have the class in one file, then the other files would have a Partial Class in them (which are part of the same class):
In one file:
Code:
Public MyClass
End Class
In a second file
Code:
Partial Class MyClass
Public Class MyInnerClass
End Class
End Class
All of this would still allow a person to create an instance of the inner class, so there's little reason to nest them if this is all you are doing. There are a couple ways to ensure that inner classes can't be created when they shouldn't be. One thing you could do is put the whole thing into a class library. They you can declare the outer class as Public and the inner class as Friend. Any project referencing the dll can create an instance of the outer class, but they won't even know about the inner class, since things declared Friend are not exposed outside the assembly.
I'd also say that you almost certainly don't want to be using Shared, there. It might seem to work, but it almost certainly doesn't do what you want, and you'll end up regretting it.
My usual boring signature: Nothing
-
Dec 1st, 2022, 11:22 PM
#9
Thread Starter
Junior Member
Re: Noob help with "nesting" classes!
Hello all,
I've spent a considerable amount of time getting my feet wet in VB.net. Lots to learn (so many modifiers, etc).
So, I am currently using the approach where the classes are built un-nested. And the constructor sets their references. Indeed I see the flaw with my "solution" earlier. Totally incorrect. My point for "nesting classes" is that I want a clean hierarchical design. Much like you see in OOP and especially VBA. Similar to that of a code library / namespace. I am considering having the children be hidden from intellisense, unless accessed through the parent. But this is not a huge requirement. In that case, I assume the classes would have to be nested.
Ultimately I have learned a lot about accessibility with this little project.
I had a bit of cognitive dissonance here because VBA tainted me with not having constructors. And therefore, setting references to a parent/child becomes hideous code at the caller level.
As for the comment on the Module being inserted.... I am testing the class with Main() in the same file. Again, I know nothing about how to actually use Visual Studio other than what I know from VBA
jmcilhinney, thanks for your code provisions. Very useful.
Shaggy Hiker, you bring up a good point about VBA and the whole 'shared' thing. I do understand that Shared is NOT a solution for accessibility between child/parent classes like I suggested.
I have not explored partial classes yet at all and not sure what that even means!
Thanks all
-
Dec 2nd, 2022, 11:19 AM
#10
Re: Noob help with "nesting" classes!
Partial classes was introduced in VS2005. Prior to that time EVERY part of a class had to be in a single file. That may not sound too bad for you, but if you take a close look at a form, you'll see why it was painful. Depending on selections you have made, you may or may not be seeing the .designer.vb file associated with every form. Forms in .NET are just plain ol' .NET code. You could write it all yourself...if you were a masochist. As it is, it's tucked away in the .designer.vb file. Take a look at one (you may have to hit the Show All Files icon in Solution Explorer, if the file isn't visible). There's a lot of fairly dull code in there, but the key point is that for any reasonably sizable form, there really is a LOT of code there. Prior to partial classes, ALL of that code was stuffed into just the one code file along with all your event handlers and anything else you wrote. It would be put into a Region block at the top of the file, along with a comment suggesting that you not mess with it, but it was all there. Total nuisance.
So, all that a partial class is, is a means to spread the code associated with a class definition across multiple files. By far, the most common use of this is so that all the designer generated code can be put off in the .designer.vb file so you don't have to see it all the time, and are less likely to mess things up by altering it, but that's all it is doing. You can use partial classes yourself, as I mentioned. It's just telling the compiler, "this code here is actually part of that other class that you already know about." That is rarely done, because a class so large that it sprawls across multiple files is usually a bad idea.
I'm using that because I have a class library (which is just a dll) where there are some classes that make no sense outside of a different class. I certainly could have moved them outside of the container class. They can only be created in that dll, so it's not like anybody would try to make an instance of one of them on their own. They won't even know about them. However, I wanted to make it rather explicitly clear in the code that the class has no meaning outside of the container, so I made them classes in the container. It's the only time I've done that, and as I said, I didn't need to. It really gained nothing at all, aside from making it abundantly clear what my intent was.
My usual boring signature: Nothing
-
Dec 2nd, 2022, 11:21 AM
#11
Re: Noob help with "nesting" classes!
One other point is that Main() is rarely used, these days, though there are times when it is the right way to go. From what you've said, you sound like you have found one of those cases. Most programs use a startup form. There is always an entry point to a program, and that entry point, by convention, is a Sub Main(), but it's usually hidden. It's not much of a point.
My usual boring signature: Nothing
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|