Static self referencing classes, a good idea or not?
#1 Members - Reputation: 108
Posted 10 November 2012 - 05:53 AM
I have some classes in my application that only ever get instantiated once - for example, a class that defines application settings and properties. However, when I want to reference this class instance from another class, I'm kinda stumped because I don't have a visible reference to my class instance.
Sure, I could pass the class instance reference into the functions that need it, but that seems ugly.
Instead, I've added a static reference to the class instance, and can therefore refer to that instance from any other class.
Example:
[source lang="java"]public class Settings{ // static reference to a settings object public static Settings ref; public Settings() { // apply a self-reference settings = self; } private void doSomething() { ... }}[/source]
So, from another class file entirely, I can refer to my single Settings class instance by using the in-built static reference, giving me access to its private methods:
[source lang="java"]Settings.ref.doSomething();[/source]
Is this an acceptible method of doing this? Or is this type of self-referencing frowned upon? Should I just make all required 'public' members and methods in the class static instead?
[source lang="java"]public class Settings{ public Settings() { // do nothing } public static void doSomething() { ... }}[/source]
I'm looking forward to some insight on this!
Thanks all!
#2 Members - Reputation: 5899
Posted 10 November 2012 - 06:26 AM
Of course, using a global instance of the class, or making all the members static, all have the same problem.
The code I work with most days has a huge class of which only one instance can exist, and we have been living with it for years, although it's a mess and we have tons of examples of interesting things we could do if we could create more than one copy. The rest of the code (I am talking hundreds of thousands of lines of code) use this class all over the place.
Passing your Settings object around is not ugly: It's making a dependency explicit.
#3 Members - Reputation: 108
Posted 10 November 2012 - 06:43 AM
It might help to give some background on the class. It's a Canvas for a drawing / modelling application, so I know for a certainty that there can only ever be one instance of the class active at any time (this isn't a multiple-workspace type of project). A workspace can only have one canvas.
Perhaps I need to think about reorganising the communication of data between the classes outside of the workspace so that rather than relying on a call directly to a static method inside of the Canvas object, I can pass a reference to the (only) instance of the Canvas to the required classes as an argument.
It'll just mean a bunch of refactoring - but eh, if we had a few bucks everytime we did that...
Edited by PixelPrime11, 10 November 2012 - 06:44 AM.
#4 Members - Reputation: 338
Posted 10 November 2012 - 09:47 AM
[source lang="java"]public abstract class Settings { private static final SingletonHolder <Settings> HOLDER = new SingletonHolder<Settings>("implementation.property"); public static final Settings getInstance() { return HOLDER.getInstance(); } public abstract void foo();}public class DefaultSettings extends Settings { public void foo() { // Do your thing }}public class SingletonHolder <Type> { private final <Type> instance; public SingletonHolder(String property) { this.instance = Class.forName(System.getProperty(property)).newInstance(); } public Type getInstance() { return instance; }}[/source]
For the sake of brevity, I didn't write the exception handling code, and the SingletonHolder should be aware of changings on the value of the system property used to fetch the implementation's class name.
Edited by Bubsy, 10 November 2012 - 09:48 AM.
#5 Moderator* - Reputation: 5411
Posted 10 November 2012 - 10:26 AM
The argument that "you might need more than just one" is true, but I think it pales in comparison to the huge pain in the butt the complex, overly coupled system that grows from global variables. Debugging gets complicated (as changes to global variables are hidden by the fact they're buried deep in some code), and overall the design goes to crap as the global variable tumor begins to spread and more objects start referring to other objects that they really, really have no need to. At least they wouldn't have such a need if things were designed well.
And for what does need to be accessed and shared, thankfully we have parameters we can pass to function calls. This makes program control flow much easier to follow and much less error prone (because you, the programmer, may forget part A changes global variable B, which affects part C; passing a parameter makes this relationship and dependency explicit and hopefully you'll have less brain farts).
#6 Members - Reputation: 1095
Posted 11 November 2012 - 06:25 PM
If the function that needs the reference is a method in some other object, you could make it so the object stores the reference. That way you can set it up in the constructor of said object or change it with a setter method later.
Besides, it gives you a good insight into your code when you think "Well, this object always used a single instance of this class... What happens if I switch it along the road? Is it safe? It crashes? It keeps working?"
My journal: Making a Terrain Generator
#7 Members - Reputation: 3335
Posted 11 November 2012 - 09:34 PM
It's a Canvas for a drawing / modelling application, so I know for a certainty that there can only ever be one instance of the class active at any time (this isn't a multiple-workspace type of project). A workspace can only have one canvas.
You mean you don't have multiple canvases for layer effects? For undo/redo? For offscreen loading/saving? For multiple screens/multiple windows for model merging?
Having this sort of side effect in the constructor is decidedly undesirable even if you want a single common/default instance.






