开发者

Quick-and-dirty class constructor for MATLAB?

开发者 https://www.devze.com 2023-01-28 01:47 出处:网络
I am trying to make MATLAB a bit more usable than it is (for me), and one of the things which I always wanted to fix is a better class constructor. I want to have the following interface:

I am trying to make MATLAB a bit more usable than it is (for me), and one of the things which I always wanted to fix is a better class constructor. I want to have the following interface:

MyClass.new(some_args).method1;

# instead of classical:
obj = MyClass(some_args);
obj.method1;

I can easily achieve this by defining a static method new:

classdef MyClass
  methods
    function obj = MyClass(varargin); end
    function method1(obj,varargin); end
  end

  methods (Static)
    function obj = new(varargin); obj = MyClass(varargin{:}); end
  end
end

But this requires adding such method to all classes, and therefore it 开发者_Python百科is not very elegant/convenient. I thought that I could go around it by defining a common class with the following constructor

classdef CommonClass
  methods (Static)
    function obj = new(varargin)
      # getting name of the current file (Object), i.e. basename(__FILE__)
      try clear E; E; catch E, [s, s] = fileparts(E.stack(1).file); end;
      # creating object with name $s
      obj = eval([s '(varargin{:})']);
    end
  end
end

classdef MyClass < CommonClass
end

However, this doesn't work because MATLAB calls new() from Object.m, and therefore I get instance of Object instead of MyClass.

Any ideas how I can improve it?


EDIT1:

I would like it to work also for classes created inside other ones:

classdef MyAnotherClass < CommonClass
  methods
    function obj = MyAnotherClass
      child = MyClass.new;
    end
  end
end

>> MyAnotherClass.new


Personally, I don't see the problem with calling the constructor as is, but if you do want to have it called via new, the getStaticCallingClassName below might be of use to you.

Here's how you'd use it:

classdef CommonClass
  methods (Static)
    function obj = new(varargin)
      %# find out which class we have to create
      className = getStaticCallingClassName;
      constructor = str2func(sprintf('@%s'className));
      %# creating object with name $s
      obj = constructor(varargin{:});
    end
  end
end

classdef MyClass < CommonClass
end

With this, you can call

obj = MyClass.new(input,arguments);

And here's getStaticCallingClassName:

function className = getStaticCallingClassName
%GETSTATICCALLINGCLASSNAME finds the classname used when invoking an (inherited) static method.
%
% SYNOPSIS: className = getStaticCallingClassName
%
% INPUT none
%
% OUTPUT className: name of class that was used to invoke an (inherited) static method
%
% EXAMPLE
%
%   Assume you define a static method in a superclass
%       classdef super < handle
%       methods (Static)
%           doSomething
%               % do something here
%           end
%       end
%       end
%
%   Also, you define two subclasses
%       classdef sub1 < super
%       end
%
%       classdef sub2 < super
%       end
%
%   Both subclasses inherit the static method. However, you may be
%   interested in knowing which subclass was used when calling the static
%   method. If you call the subclass programmatically, you can easily pass
%   the name of the subclass as an input argument, but you may want to be
%   able to call the method from command line without any input and still
%   know the class name.
%   getStaticCallingClassName solves this problem. Calling it in the above
%   static method 'doSomething', it returns 'sub1' if the static method was
%   invoked as sub1.doSomething. It also works if you create an instance of
%   the subclass first, and then invoke the static method from the object
%   (e.g. sc = sub1; sc.doSomething returns 'sub1' if .doSomething calls
%   getStaticCallingClassName)
%   
%   NOTE: getStaticCallingClassName reads the last workspace command from
%         history. This is an undocumented feature. Thus,
%         getStaticCallingClassName may not work in future releases.
%   
% created with MATLAB ver.: 7.9.0.3470 (R2009b) on Mac OS X  Version: 10.5.7 Build: 9J61 
%
% created by: Jonas Dorn
% DATE: 16-Jun-2009
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% get the last entry of the command line from the command history
javaHistory=com.mathworks.mlservices.MLCommandHistoryServices.getSessionHistory;
lastCommand = javaHistory(end).toCharArray';%'# SO formatting
% find string before the last dot.
tmp = regexp(lastCommand,'(?:=|\.)?(\w+)\.\w+\(?(?:.*)[;,]*\s*$','tokens');
try
    className = tmp{1}{1};
catch me
    className = [];
end
% if you assign an object, and then call the static method from the
% instance, the above regexp returns the variable name. We can get the
% className through getting the class of xx.empty.
if ~isempty(className)
    className = evalin('base',sprintf('class(%s.empty);',className));
end


I could be missing something, but what's wrong with

method1(MyClass(some_args))

? (I use this pattern all the time).

0

精彩评论

暂无评论...
验证码 换一张
取 消