Singleton Construction Question

Hey all,

I have three different classes that I would like to use as singletons in my project. “Easy.”, you say. But hold on. These classes are all subclasses of a parent class. There are multiple methods in that parent class that are used to perform operations since these 3 classes are similar but different. There is only going to be one of each of these classes in the project. Right now I create a new instance of each class type when the app and store them in a global module. Then I call each of those instances when wanting to do something. However, that just seems messy.

But so does creating the singleton as I need to use shared methods. I would need to create shared methods in each subclass that points to the already existing method in the parent class. I thought about making the methods in the parent class shared, but shared methods are shared across ALL instances of a class, so wouldn’t that kind-of muck things up as I have three unique subclasses and now these parent methods which do different things based upon the type of instance - how would I sort that out???

So for example, I have a method in the parent class called “set.” Some of the code is as follows:

If DoChange Then
  
  If ControlType <> ControlTypeEnumeration.Sequence Then
    QueueChanges(IndexToUse, GroupIndex)
  Else
    RaiseEvent MakeChange(IndexToUse,DoChange)
  End If
Else
  ChangeSuccess = True
  ChangeAction
End If

ControlType is an enumeration that defines the type of control the class is representing. It’s different obviously for each subclass. So since the shared method is shared at the parent level between all instances, I won’t get a proper answer for ControlType, will I?

What’s the best way to do this? The way I have it now works and is simple, but using singletons would be convenient.

From the slightly muddled way you have described your problem I would say that your class structure isn’t optimal yet.

What is the intent of your classes? Why do you need to use shared methods? Why do you want singletons for controls?

It’s not a control. If I’ve used the wrong verbiage, I apologize.

What I am doing is taking code that had been in UI controls and putting it into classes instead. Long story around why I want to do that but I am wanting to disconnect the UI layer from the bits of code that do all the heavy lifting. One reason is I have a web app as well and while the web app and desktop share a lot of common code they are still two separate apps and I have to maintain much of the same duplicated code. I want to ultimately have a single service app or daemon that does all the important actions I need and then the desktop app web app simply communicate to the service app what needs to be done. That’s just one reason.

I am considering using singletons as these classes are all only used once in the app. There are never going to be more instances than one of each. Make sense?

Hmm… I don’ see a need for the singleton. The singleton - as far as I understand it - is to prevent multiple instances. If it would be theoretically okay to have a second instance I’d skip the singleton. I have quite a few classes in my projects that are used only once and aren’t singletons.

That’s just it - it would not be OK to have a second instance of each item. I would never code it to create a second instance, but there should only be one instance of each class. Maybe creating the singleton is more work than necessary.

It’s easy.

  1. Make all constructors private.
  2. Add a private shared property to the class thisClass as Classname
  3. Add a public shared method named Create which looks like this:

if thisClass= Nil then ThisClass = new ClassName End If Return ThisClass

Greg,

Yeah, I understand that. But then can I access methods of the parent class simply by calling that method? So can I then call:

MyCustomClass.Set(SomeValue)

Where MyCustomClass is the Singleton and Set is a method in the parent class that is not a shared method. I don’t think so. And I can’t make the method in the parent class a shared method or can I? That’s the whole nub of my problem. You have to call shared methods from outside of the class.

Ah heck, I’ll write some code and mess with it and see what happens! :slight_smile:

OK - so I just took one of my methods in my parent class and made it a shared method. So that opens up a whole can of worms as shared methods can’t access instance properties - only shared properties. Well, my instance properties are used to define things in each subclass, and if I share them, suddenly it dilutes all my subclasses.

So short of making each subclass a singleton and adding in identical shared methods to each one that call methods on the parent class, I don’t think there’s a way to do this…

The trick is that the super’s method and the subclass’ shared method can’t have the same name.

https://www.dropbox.com/s/naytoe56xdgtdc2/Singleton.xojo_binary_project.zip?dl=1

Thanks, Greg. That’s what I was afraid of. I have to effectively re-create the methods in each subclass as shared methods (well, not completely - those shared methods call the method in the parent class - but I’m effectively duplicating code). So simply for the privilege of having singletons, I have to basically create 3 times as many methods that are all doing the same thing. It seems much simple to just instantiate a single instance of each class in this case. I don’t see a benefit then to using these classes as singletons.

On the other hand is there some “proper” programming reason why I should use them as singletons?

I’m confused by …

You’d need to do that for singletons regardless, by their very definition you’re creating an instance of the class, but can’t make more than one.

With Greg’s example of using a shared Create factory function on the subclasses (and only the subclasses) that enforces that only one instance of each is alive, you can create an App level property for each subclass early in the app’s life safe in the knowledge that any function that tries to create a new instance will get a reference to that pre-existing instance and therefore all its current property state.

[quote=320063:@Ian Jones]I’m confused by …

You’d need to do that for singletons regardless, by their very definition you’re creating an instance of the class, but can’t make more than one.

With Greg’s example of using a shared Create factory function on the subclasses (and only the subclasses) that enforces that only one instance of each is alive, you can create an App level property for each subclass early in the app’s life safe in the knowledge that any function that tries to create a new instance will get a reference to that pre-existing instance and therefore all its current property state.[/quote]

Well, actually, any function that would attempt to create a new instance of a singleton will get a compile time error since the constructor methods in singletons are private.

Anyhow, yes, I know you need to create an instance in both cases. In the singleton case, you are doing it as a shared property of the class. In my case, it’s simply as a property in a module. The difference is, I have a parent class that has several methods in it that get called throughout my app in various places. I think there are about 3 of those methods. I have 3 subclasses of that parent class. If I want to make those three subclasses singletons, now I have to create 3 additional shared methods in each subclass (9 total) that do nothing more than call the method of the parent class and are effectively duplicate code.

That’s where I don’t think having a singleton makes sense in my case.

Maybe i’ve lost track of what the problem actually is but does this help?

App

Class App
Inherits ConsoleApplication
Events

Function Run(args() as String) As Integer Dim c1 As cSingleton
Dim c2 As cSingleton
   c1 = cSingleton.Get
   c1.incValue
   c2 = cSingleton.Get
msgbox Str(c2.value) 
End Function

End Class


cSingleton
Class cSingleton

Methods
Protected Sub Constructor()
End Sub

Sub IncValue()
value = value + 1
End Sub

Shared Methods
Shared Function Get() As cSingleton
If mInstance = Nil Then
mInstance = New cSingleton
End If
Return mInstance
End Function

Properties
value As Integer

Shared Properties
Private Shared mInstance As cSingleton 
End Class

OK. I think people have gotten lost and have not read the original context in which I write this. I do not need help to create a singleton. My question was more involved than that. Here I go again:

1.) I have a parent class call MultipleItemStreamControl. That class has a number of methods and properties.

2.) I have three subclasses:
a.) PresetController
b.) GroupController
c.) SequenceController

3.) There is an enumeration in the parent class that gets set at construction time in the subclass which defines what happens when certain methods in the parent class are called.

4.) There is only ONE instance of each of these subclasses in the app (hence the idea of a singleton).

5.) Right now in the open event of the app, I have the following:

MSPresetController = New PresetController
MSGroupController = New GroupController
MSSequenceController = New SequenceController

These instances are stored in a module.

6.) At various points in the code, I call things like:

MSPresetController.Set(1) MSGroupController.Set(1,2) MSSequenceController.set(2)

Where the “Set” method (and this is VERY IMPORTANT for my question and sets the context) is in the parent class, MultipleItemStreamControl.

There are additional methods as well.

7.) If I were to create singletons of each of these subclasses, I would need to have a shared method in each subclass that calls the method in the parent class. So in the case of the “Set” method, I need to create what are basically 3 duplicate methods (one in each subclass) that references the instance and calls the method in the parent class.

8.) I have to create 3 effectively identical methods for every method of the parent class that I want to access in my code.

9.) This doesn’t seem very efficient or useful. So I am staying with what I have now. My original question was if there was some other way to construct the singleton so that I would NOT have to create duplicate shared methods in each instance. But there is not. You have to use shared methods with Singletons.

Make sense now?

why is it you think you need shared methods or that you need to duplicate any code ?

this should be possible just through normal subclassing etc as each instance will have its own copy of whatever instance properties there are and will call whatever inherited methods the superclass provides

And the superclass will access the right instances properties - unless of course you make them shared and then you will share one property across all 3 instances

So I set up a singleton with a shared property containing my instance. Here’s the code from Greg’s example:

Public Shared Function Create() as MyCustomClass If OnlyOneOfMe = nil then OnlyOneOfMe = new MyCustomClass End If return OnlyOneOfMe End Function

So that’s a shared function, create that you call by calling:

MyCustomClass.Create

That creates a shared property OnlyOneofMe that is the instance of the class. OnlyOneofMe is a private shared property. So it can’t be called from outside the class.

Now, the parent class in Greg’s example has a method called SetValue (following my example as he was trying to help me and did). I cannot now call:

MyCustomClass.Set because it’s not a shared method. I’ll get a compile time error.

I can’t call OnlyOneofMe.SetValue because OnlyOneOfMe is a private property. I suppose I could change the scope but that seems to defeat the idea of a singleton.

The only way to call the SetValue method is to have a shared method in the subclass that calls that parent class method. Again from Greg’s example.

Public Shared Sub Set(key as string, assigns value as Variant) OnlyOneOfMe.setvalue(key) = value End Sub

I can now call: MyCustomClass.set(some_value)

I have to create these shared methods for every parent class method I want to call as a method call has to be called from an instance and not from the class itself!

[quote=320291:@Jon Ogden]So I set up a singleton with a shared property containing my instance. Here’s the code from Greg’s example:

Public Shared Function Create() as MyCustomClass If OnlyOneOfMe = nil then OnlyOneOfMe = new MyCustomClass End If return OnlyOneOfMe End Function

So that’s a shared function, create that you call by calling:

MyCustomClass.Create

That creates a shared property OnlyOneofMe that is the instance of the class. OnlyOneofMe is a private shared property. So it can’t be called from outside the class.
[/quote]
So far so good

[quote=320291:@Jon Ogden]Now, the parent class in Greg’s example has a method called SetValue (following my example as he was trying to help me and did). I cannot now call:

MyCustomClass.Set because it’s not a shared method. I’ll get a compile time error.
[/quote]

MyCustomClass.Create.Set

CREATE either CREATES one and gives you a reference to the instance it just created OR gives you a reference to the instance that already exists

Or add another Shared method to each subclass that is “Get” that just returns the single instance stored in the shared property

The rest is normal subclassing and inheritance

Norman, that’s genius. I never thought of that…

That’s exactly the sort of input I was looking for - I thought I might be missing something - I was. Greg’s example still had the additional shared methods in it.

http://great-white-software.com/miscellaneous/jon%20ogden.zip

no genius
this is just how things should work
you need to “get” a reference to the single shared instance somehow … and create does that