What is the purpose of declaring a Class within another Class? - vb.net

I come from the VBA world where options to breakdown your code into classes, namespaces, and modules is limited. Now I just landed in a world where the options are many, and I feel lost.
I would like to know what is the purpose of declaring a Class within another Class? (see example below)
Class FirstClass
Public OnePropertyInside As String
Class SecondClass
Public AnotherProperty As String
End Class
End Class
If I create a new instance of FirstClass (say myFirstClass), SecondClass is not instantiated.
Even more bizzare (to me at least), is that intelissense offers me myFirstClass.SecondClass. Obviously, because the class is not instantiated, I cannot access any of its members.
So, is that usefull only if the SecondClass contains shared members?
To try answering that question I added a shared member within SecondClass:
Class FirstClass
Public OnePropertyInside As String
Class SecondClass
Public AnotherProperty As String
Public Shared SharedProperty As String
End Class
End Class
I ran a few tests which brought secondary questions (see comments in code)
Sub Main()
Dim myFirstClass As New FirstClass
'Works as expected
Console.WriteLine(myFirstClass.OneProperty)
'What is the difference between the two lines below?
Console.WriteLine(myFirstClass.SecondClass.SharedProperty)
Console.WriteLine(FirstClass.SecondClass.SharedProperty)
'This line cannot be compiled, this demonstrates SecondClass is not instantiated when FirstClass is.
Console.WriteLine(myFirstClass.SecondClass.AnotherProperty)
Dim mySecondClass As New FirstClass.SecondClass
'Works as expected, but I feel this hierarchy should better be dealt with through a namespace statement?
Console.WriteLine(mySecondClass.AnotherProperty)
End Sub

You can think of it as if the inner most class is a helper class of sorts. It may not even need to be used at all. Nesting the inner class(or simply nested class) inside the outer class gives you access to all of the members of the outer one. You can even access the private members inside that initial outer class.
Edit: For clarification, I mean to say that the the inner can access the private members of the outer, not the other way around.

You usually do this because you want to restrict the scope of the nested class.
So, if you only need to use this class from within the "parent" class (in terms of scope), then its usually a good idea to define it as a nested class.
If you might might need to use the class outside of its assembly, then it is better to define it as a completely separate class (in its own file), and then define your relationship accordingly. You will need to instantiate one within the other (this is the same whether its seperate or nested - so its location is largely irrelevant for that point).

When you do that, and the inner class is accessible to other classes (it's accessibility is Public or Friend), the outer class basically just works like a namespace. So for instance, using your example, you could create a new object of the nested class without ever creating one of the outer class:
Dim x As New FirstClass.SecondClass()
The most obvious benefit is the structural organization of the code, much like namespaces and code files. So, for instance, it's not uncommon to use nested classes for constants, to help better organize them:
Public Class Urls
Public Class Processing
Public Const Submit As String = "..."
Public Const Cancel As String = "..."
End Class
Public Class Reporting
Public Const Daily As String = "..."
Public Const Weekly As String = "..."
End Class
End Class
' ...
Dim url As String = Urls.Reporting.Daily
However, outside of the narrow set of situations where things like that are useful, most people would prefer to not nest public classes at all.
However, as others have mentioned, the one place where you really will see nested classes used fairly regularly is for Private ones. If you need some small helper class which will have no use to code outside of your class, there's no reason to expose it. Even if you set it's accessibility to Friend, it will still be visible to all the other classes in the same project. Therefore, if you really want to hide it from everything else, you'll want to make it a nested private class. For instance:
Public Class MyClass
Public Function GetTheIdOfSomething() As Integer
Dim d As Details = GetDetailsAboutSomething()
If d.Value Is Nothing Then
Return d.Id
Else
Throw New Exception()
End If
End Sub
Private Function GetDetailsAboutSomething() As Details
' ... return a Details object
End Function
Private Class Details
Public Property Id As Integer
Public Property Value As String
End Class
End Class

Related

Named Constructor Idiom in VB.NET?

Is using the Named Constructor Idiom possible in VB.NET? I've found many examples in C#/C++ but can't quite wrap my head around how to use it in vb.net. Seems like a better method of keeping my code readable when involving a lot of constructors with similar argument types.
I've never heard this term before, but after a quick search it sounds vaguely like the Static Factory Pattern. The idea is you make the constructor private and use a shared (static in c#) public function to create the new object.
Public Class Foo
Private Sub New()
End Sub
Public Shared Function CreateNew(param as Object) as Foo
Dim obj as New Foo()
obj.Prop = param
return obj
End Function
End Class
You sure can make Named Constructors in VB. The pattern uses a static (Shared in VB) factory method on the class itself, so that the method can be named. (Other Factory patterns involve using a separate Factory class to provide the static method.)
System.Drawing.Color is a simple example. The pattern is implemented underneath as a static (Shared) property. Since no arguments are necessary, the Get method of a Property works just fine:
Public Shared ReadOnly Property Chartreuse As Color
Usage:
Dim favoriteColor as Color = Color.Chartreuse
Or you can make static factory methods to do the same thing.
Public Class TheClass
Public Sub New()
End Sub
Public Sub New(input As String)
'do something with input
End Sub
Public Shared Function MyNamedConstructor() As TheClass
Return New TheClass
End Function
Public Shared Function AnotherNamedConstructor() As TheClass
Return New TheClass("Another Name")
End Function
End Class
As for whether this pattern is "better" than overloading constructors, that's really an opinion. Personally, I would just overload the constructors. As you can see in the example above, the constructors need to be there anyway.
I suggest using the Named Constructor pattern when you have only a few possible ways to construct your class/struct, but consumers of your class/struct will be using those few constructors often, and with different input values to those constructors (as in the System.Drawing.Color example).
The Name in 'Named Constructor' doesn't represent a name for the constructor itself, but for the object resulting from the constructor. If your named constructor can be used to create two objects that don't feel right to give the same name to, then don't give the constructor that name.

Is it possible to determine the type of a class at instantiation or convert the type afterwards without casting?

For example: I have some classes that all inherit from the same class.
Public Class MasterClass
' content
End Class
Public Class ClassA
Inherits MasterClass
'content
End Class
Public Class ClassB
Inherits MasterClass
'content
End Class
Public Class ClassC
Inherits MasterClass
'content
End Class
And I want decide on runtime which one I need. Then I can do something like this:
Private myInstance As MasterClass
If conditionA Then
myInstance = New ClassA
ElseIf conditionB Then
myInstance = New ClassB
Else
myInstance = New ClassC
End
But it can get quite long, and I still have to cast it evertime I use it.
I can assing a type to a variable, but I don't know how to use that type to create a new instance of that type..
Dim storedType As Type = GetType(ClassA)
Dim someInstance = New storedType 'Does not work
Is there a better way? Can you change the type of a variable at runtime?
I still have to cast it evertime I use it.
The idea around polymorphism and inheritance is that you don't have to cast them to use them. You can write things in such a way that the master class has all the functions etc that you need (whether or not they do anything) and then you call things as if you were just dealing with the master class but, because each child implements a different behavior, the end result is different - your program might not even know (if the child implementation came from a third party dll) what is going on but it doesn't matter
Can you change the type of a variable at runtime?
Sure, but you have to use it how it appears. Long chains of "if my object is an instance of x then cast my object as x and use method X1, else if my object is a y then cast as y and call y1" are not polymorphic/not leveraging inheritance principles properly - you're supposed to call myobject.whatever, and if my object is an x, then x1 happens and if it's a y then y1 happens
I want decide on runtime which one I need
But you don't have to do that in the class that knows about class a/b/c - each of class a/b/c can do that and hence become self contained. You can have all your instances in an array of the parent type, and visit each one asking them if they handle the condition and use the one that says it can
Consider a slightly better real world example than this artificial class a/b/c trope:
You are tasked with writing an app that can download an image (png, jpg or gif) from somewhere (http or ftp or disk location), rotate it and upload it to somewhere else
You decide to have an ImageRotator parent that specifies a CanHandle function and a Rotate function. It has 3 subclasses, one that handles jpg, one that rotates gif and one that does png. When presented with a PNG filename the JpgRotator says No when asked if it can handle it etc.
Separately you have a FileMover parent that CanHandle and has Download/Upload functions. Again, the parent doesn't implement these at all. The three subclasses implement the ability up/down an http, an ftp and a disk location
You create an instance of each rotator and put it into an array of ImageRotator type. You also create an instance of each mover onto an array that is a FileMover parent type.
Your user specifies a jpg in a http url, and to store it in a disk location at the end. You loop your FileMovers and ask each if they support the location the user provided. The http mover says yes, you invoke its download to a temp path. Then you pass he path to each rotator, the jpg rotator says yes, you call rotate. Finally, you look for another mover that can handle an output path of local disk...
Someone decides to extend your program with a plug-in dll that adds he ability to put files in and out of a db, and support tiff images.. ignoring the magic of how instances of their classes come to be in your arrays, you can see that your program can now move these new locations and types because the logic for whether they handle db/tiff is not a part of your code.. your code just treats everything consistently
In this case Interfaces are the best choice
Interface ABC
Property Text As String
Property Value As Integer
End Interface
Public Class MasterClass
End Class
Public Class ClassA
Inherits MasterClass : Implements ABC
Property Mystr As String Implements ABC.Text
Property Sum As Integer Implements ABC.Value
End Class
Public Class ClassB
Inherits MasterClass : Implements ABC
Property MyText As String Implements ABC.Text
Property Value As Integer Implements ABC.Value
End Class
Public Class ClassC
Inherits MasterClass : Implements ABC
Property str As String Implements ABC.Text
Property Value As Integer Implements ABC.Value
End Class
usage
Dim myABC As ABC
If conditionA Then
myABC = New ClassA
ElseIf conditionB Then
myABC = New ClassB
Else
myABC = New ClassC
End If
myABC.Text = "Interface"

Too many identical simple methods using an interface

I have a few dozen classes which all implement the same interface and many of the methods have identical implementation. I have to do a lot of copy and paste whenever I add a new class. How can I get less code duplication?
I've heard that you should put the common code in a helper class but a lot of these methods are really trivial so calling a helper method is barely any simpler than doing the actual work.
Inheritance would save re-declaring all these methods but it would make it messy for the few classes that don't have the identical implementation.
Examples:
Identical in nearly every class...
Public Sub ThingWasDeleted(ByVal deletedThing As Thing) Implements Iinterface.ThingWasDeleted
If MyThing Is deletedThing Then
MyThing = Nothing
End If
End Sub
...but occasionally different:
Public Sub ThingWasDeleted(ByVal deletedThing As Thing) Implements IInterface.ThingWasDeleted
'Do nothing
End Sub
Identical in every class but already just as simple as calling a common helper method:
Public ReadOnly Property DisplayName() As String Implements IInterface.DisplayName
Get
Return DisplayNameShared
End Get
End Property
If you put these methods in a helper class, wouldn't that make it just as messy (if not more) than having an abstract base class where you can override the base class's functionality when needed?
For example:
Public MustInherit Class BaseClass
Public ReadOnly Property DisplayName() As String
Get
Return DisplayNameShared
End Get
End Property
Public Overridable Sub ThingWasDeleted(ByVal deletedThing As Thing)
If MyThing Is deletedThing Then
MyThing = Nothing
End If
End Sub
End Class
This provide a definition of the property that all inheriting classes can use, and gives the inheriting class an option to override and create their own implementation of ThingWasDeleted.
For example:
Public Class MyClass
Inherits BaseClass
Public Overrides Sub ThingWasDeleted(ByVal deletedThing As Thing)
' Do nothing
End Sub
End Class
On the other hand, if you wrote a helper class, you'd have to define every method, and the developer (which may or may not be you) would have to know which method to change. Additionally, instead of having the option to use the existing functionality in the base (abstract) class, every class you create will have to call each of the proper helper methods.
Personally, I prefer the former option, mainly because the inheriting classes don't have to call anything to get the base functionality established in the base class, and can override what they need to on a case-by-case basis. Conversely, having them all in a helper class means you have to at least write the code to call each of the necessary helper methods in every class you have.

vbscript static class variables/methods?

Is there a way to have one variable per class in vbscript?
If not what is the best way to emulate it? Prefixing a global variable declared next to the class?
Also is there a way to declare static/class methods(for a static constructor) or am I force to prefix a function?
In languages that support class-level/static data or methods you can
associate/bind data or methods explicitly to the set of objects defined by the class. So you can have Customer.Count and Product.Count and a plain Count (or ##Count) in Customer code will access the right number.
use such data or method without having an instance of the class (yet).
VBScript does not support static data or methods. You have to use global data or functions/subs and do the associating in your mind (perhaps with a little help from a naming convention). Accessing these 'static'=global elements without an object is trivial, but - obviously - should be done with care.
You can embed one or more singleton objects or code references (GetRef()) in your objects to bind them closer to the class, but that will increase the size of the instances.
You can do something like this to sort of emulate a static class:
Class Defines_
Public Sub DoSomethingUseful
End Sub
End Class
Dim Defines : Set Defines = New Defines_
...
Defines.DoSomethingUseful
This can be used to give you something analogous to constructors (really, factory methods):
Class Something
Private mValue
Public Property Get Value : Value = mValue : End Property
Public Property Let Value(x) : mValue = x : End Property
End Class
Class SomethingFactory_
Public Function Create(value)
Set Create = New Something
Create.Value = value
End Function
End Class
Dim SomethingFactory : Set SomethingFactory = New SomethingFactory_
...
Dim something : Set something = SomethingFactory.Create(5)

Factory method for generics in VB.NET

I want to create a factory for generic classes in VB.NET and I am running into issues.
What I have are two interfaces:
IPersistentObject and IPManagerBase(Of T as IPersistentObject)
The logic is that for each type of peristent object I have a corresponding manager class handling query logic.
Now I have a base class like this:
public class PManagerBase(Of T as IPersistentObject) Implements IPManagerBase(of T)
So, now in the real world I have a persistent type "PUser" and a corresponding manager declared like this:
public class PUserManager implements PManagerBase(Of PUser)
I have about 100 of those persistent objects and corresponding manager classes.
Now I want to have a factory, which I would invoke like this (removing the details):
MyFactory.CreateManager<PUserManager>()
I am creating my Factory like this
public class MyFactory
public shared function CreateManager(Of T as {PManagerBase(Of IPersistentObject), New}) as T
return new T()
end function
end class
Looks great.
Now I want to invoke it:
Dim myManager = MyFactory.CreateManager<PUserManager>()
What happens?
I get a compile error: "PUserManager does not implement/inherit PManagerBase(Of IPersistentObject)". I get the message in German so this is a free tranlation.
What would I need to change to make this running?
It works if I declare my factory like this:
public class MyFactory
public shared function CreateManager(Of T as {PManagerBase(Of PUser), New}) as T
return new T()
end function
end class
But then the benefit is gone, since it works only for Managers of the PUser object.
A better solution is
public class MyFactory
public shared function CreateManager(Of T as {PManagerBase(Of U), New}, U as IPersistentObject) as T
return new T()
end function
end class
This works, but I have to call my factory method like this now:
Dim myManager = MyFactory.CreateManager<PUserManager, PUser>()
I don't like this since this is redundant and I don't need U at all in the function. In it's declaration PUserManager is tied to PUser.
Is there a better way? Why is PUserManager not inheriting from PManagerBase(Of IPersistentObject)?
This is a problem with generics, if you are using VS 2010 you may want to take a look at covariance and contravariance and modify your IPManagerBase definition accordingly.