Destroying an instance of a Matlab Singleton class without calling `clear all`
According to Matlab documentation , to create a Singleton design pattern you need to set a variable persistent
inside a static function for your singleton object e.g.
classdef (Sealed) SingleInstance < handle
methods (Access = private)
function obj = SingleInstance
end
end
methods (Static)
function singleObj = getInstance
persistent localObj
if isempty(localObj) || ~isvalid(localObj)
localObj = SingleInstance;
end
singleObj = localObj;
end
end
end
It is almost impossible to "destroy" a singleton instance. I tried to clear SingleInstance
, clear getInstance()
, clear SingleInstance.getInstance()
, clear functions
, clear variables
and other combinations. The only way for a constant variable localObj
in a static getInstance()
class method SingleInstance
is to call clear all
.
I'm fine with a call clear all
before calling my Matlab OO application. However, I am using the Matlab unit test framework and there are unit tests where I would like to test different ways of instantiating singleton classes. However, for this I will need to call clear all
, which will cause the Matlab unit test framework to stop working.
Does anyone know a way to clear a constant variable inside static methods of Matlab classes without calling clear all
? Or else, does anyone know how to implement the Singleton design pattern without using variables persitent
? Or at least as a call clear all
inside unit tests without breaking the unit test infrastructure?
source to share
You should use delete
or see Doc
clear
You can also look in the family clear classes
, but that won't work for you as it does the same thing clear all
and also removes the class definition.
You have nothing to change in the construct of the singleton type class to destroy the instance of the object handle
you should be using delete object2dispose
. When you use clear object2dispose
, you only clear the variable on the stage that contains the handle to your object, but you do not destroy the object itself. This is why when you call the method getInstance
, you still see that the descriptor is stored in a constant variable localObj
(which is one of the purposes of storing the descriptor you saved).
So if I use
sobj = SingleInstance.getInstance %// instantiate object
clear sobj %// clear it ? (... not really)
sobj = SingleInstance.getInstance %// To see the state of "localObj"
I stopped in the debugger while executing the third line and I get:
My variable sobj
disappeared from the workspace when I called clarity, but the object still existed in memory (and the handle is still being saved to the variable localObj
).
If now replace the second line with
delete(sobj)
In the workspace, you get:
>> sobj sobj = handle to deleted SingleInstance
And on the next call getInstance
in the debugger, I get:
localObj
that appear on the Stage still appear as a handle SingleInstance
, but it knows that the object has been deleted.
So, in the design of your class, you can check the state localObj
before proceeding with it.
the function isvalid
is useful to know if the handle is pointing to a real object or not.
source to share
My first thought is that you should avoid single and other forms of global state whenever possible, not only for validation, but also for cleanliness and interface integrity. More details here and here .
Another thought is that you can issue the following call:
classdef FuadTest < matlab.unittest.TestCase
methods(Test)
function testSomething(testCase)
clearClasses;
% Do other stuff
end
end
end
function clearClasses
clear classes;
end
This is where you need to put the call to clear classes in your own local function (or private method, static method, etc.) so that you understand the clarity in your scope and don't clear all other variables in yours (for example testCase
). If in your own function you don't need any other variables in this scope so that you can clean up the classes efficiently.
A word of warning, however, using clear classes in this way is really a scent trying to tell you something (primarily to avoid global state) and you should expect to run into idiosyncrasies. For example, I believe that calling clear classes cleans up the profiler data, so you won't be able to effectively measure your code coverage using the CodeCoveragePlugin .
Hoki's answer is fine as long as you are fine with the ability for the user to clear one and only instance, which can also clear the global state that your application depends on and can cause errors in the future if you're not careful.
Hope it helps!
source to share