Implementing an hgsetget subclass

1 Ansicht (letzte 30 Tage)
Andrew Newell
Andrew Newell am 24 Feb. 2011
I would like to create a subclass of hgsetget that would show this kind of behavior:
>>u=unit('SI');
>>set(u) % set behavior 1
System: '[{SI} | cgs]'
>>set(u,'System') % set behavior 2
[{SI} | cgs]
>>set(u,'System','cgs') % set behavior 3
>>get(u,'System')
ans =
cgs
In other words, much like the behavior you see for a figure handle. Following the example in Implementing a Set/Get Interface for Properties, I tried this code:
classdef unit < hgsetget
properties
System = '';
end
methods
function H = unit(str)
if nargin > 0
H.System = str;
end
end
function H = set.System(H,str)
H.System = str;
end
end
end
This gets set behavior 3 right, but how do I add the other two? The closest I have come so far is to simply program all the cases into an overloaded set method, and get rid of set.System. But if I add a few more properties, this gets quite ugly. Does anyone know an elegant way of doing this?

Akzeptierte Antwort

Andrew Newell
Andrew Newell am 25 Feb. 2011
O.k., this works:
classdef unit < hgsetget
% This is just a test class for using SET in an HGSETGET subclass.
properties
System = '';
end
methods
function H = unit(str)
if nargin > 0
H.System = str;
end
end
function varargout = set(H,varargin)
S = struct('System','[{SI} | cgs]');
switch nargin
case 1
if nargout < 1
disp(S)
else
varargout{1} = S;
end
case 2
if nargout < 1
disp(S.System)
else
varargout{1} = S.System;
end
case 3
H.System = varargin{2};
otherwise
error('unit:wrongNumberOfArguments', ...
'Wrong number of arguments to SET command.')
end% switch
end% set
end% methods
end% classdef
But I still wonder - is there an implementation that involves a function SET.SYSTEM?

Weitere Antworten (3)

Jiro Doke
Jiro Doke am 26 Feb. 2011
This is interesting. It does seem like the documentation isn't complete. It mentions how calling the set with a particular syntax returns the possible values of a property, but it doesn't explain how to specify those possible values.
Here's something that I put together to try to achieve what you want, while making it somewhat extensible to multiple properties:
classdef MyClass < hgsetget
properties
Prop1
Prop2
end
properties (Hidden, Constant)
Prop1_values = {'SI', 'cgs'}
Prop2_values = {'C', 'F'}
end
methods
function varargout = set(obj, varargin)
% Allow only one output and no more than 3 input arguments
error(nargoutchk(0, 1, nargout, 'struct'));
error(nargchk(1, 3, nargin, 'struct'));
switch nargin
case 1 % set(h) syntax
propnames = properties(obj);
if nargout
s = cell2struct(cell(size(propnames)), ...
propnames, 1);
for id = 1:length(propnames)
s.(propnames{id}) = set(obj, propnames{id});
end
varargout{1} = s;
else
for id = 1:length(propnames)
set(obj, propnames{id});
end
end
case 2 % set(h, 'PropertyName') syntax
allprops = properties(obj);
if ismember(varargin{1}, allprops)
if nargout
varargout{1} = MyClass.([varargin{1}, '_values']);
else
fprintf('%10s: %s\n', varargin{1}, ...
toString(MyClass.([varargin{1}, '_values'])));
end
else
error('Invalid property "%s" for class "%s".', ...
varargin{1}, class(obj));
end
case 3 % set(h, 'PropertyName', value) syntax
allprops = properties(obj);
if ismember(varargin{1}, allprops)
val = validatestring(varargin{2}, ...
MyClass.([varargin{1}, '_values']), ...
mfilename, varargin{1});
obj.(varargin{1}) = val;
else
error('Invalid property "%s" for class "%s".', ...
varargin{1}, class(obj));
end
if nargout
varargout{1} = [];
end
end
end
end
end
function str = toString(in)
in{1} = ['{', in{1}, '}']; % first input is the default
str = sprintf('| %s ', in{:});
str = ['[', str(2:end), ']'];
end
I have Hidden, Constant properties that specify the possible property values, and the set method queries that information. So whenever I create a new property, I create a corresponding Prop#_values property.
EDIT: I've implemented a Setter for the properties. In this example, instead of creating a separate Setter method for each property, I made it as a part of the set method (see case 3 in the switch statement). Since the Prop#_values contain the valid string values, I use that to validate the input.
Test...
>> a = MyClass;
>> set(a)
Prop1: [ {SI} | cgs ]
Prop2: [ {C} | F ]
>> set(a, 'Prop2')
Prop2: [ {C} | F ]
>> set(a, 'Prop1', 'cgs')
>> get(a, 'Prop1')
ans =
cgs
>> set(a, 'Prop2', 'CF')
??? Error using ==> MyClass
Expected Prop2 to match one of these strings:
C, F
The input, 'CF', did not match any of the valid strings.
Error in ==> MyClass>MyClass.set at 46
val = validatestring(varargin{2}, ...
>>
  7 Kommentare
Jiro Doke
Jiro Doke am 28 Feb. 2011
@Andrew: That's great! Would you care to share that on the File Exchange? It seems like there is no simple way of doing it with HGSETGET, so your approach might be the best currently.
Andrew Newell
Andrew Newell am 28 Feb. 2011
@Jiro, I intend to do just that. It was a bit of work making SET capable of taking all the different combinations of arguments! I have submitted a new question, though, about making my class abstract.

Melden Sie sich an, um zu kommentieren.


Andrew Newell
Andrew Newell am 25 Feb. 2011
Here is a simple attempt to get the full functionality:
classdef unit < hgsetget
% This is just a test class for using SET in an HGSETGET subclass.
properties
System = '';
end
methods
function H = unit(str)
if nargin > 0
H.System = str;
end
end
function varargout = set(H,varargin)
switch nargin
case 1
varargout = {struct('System',{'SI','cgs'})};
case 2
varargout{1} = '[{SI} | cgs]';
case 3
H.System = varargin{2};
otherwise
error('unit:wrongNumberOfArguments', ...
'Wrong number of arguments to SET command.')
end% switch
end% set
end% methods
end% classdef
However, the behavior is not quite the same:
>> u = unit;
>> set(u)
ans =
1x2 struct array with fields:
System
>> set(u,'System')
ans =
[{SI} | cgs]
>> set(u,'System','cgs') >> get(u,'System')
ans =
cgs

Andrew Newell
Andrew Newell am 10 Mär. 2011
I have submitted an extension of hgsetget to the FEX: handleGraphicsSetGet class.

Kategorien

Mehr zu Argument Definitions finden Sie in Help Center und File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by