MATLAB的快速脏类构造函数?

时间:2010-12-03 21:02:28

标签: oop class matlab constructor

我试图使MATLAB比它更有用(对我而言),我一直想要解决的一个问题是更好的类构造函数。我想拥有以下界面:

MyClass.new(some_args).method1;

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

我可以通过定义静态方法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

但是这需要在所有类中添加这样的方法,因此它不是非常优雅/方便。我认为我可以通过使用以下构造函数

定义一个公共类来绕过它
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

但是,这不起作用,因为MATLAB从new()调用Object.m,因此我获得了Object而不是MyClass的实例。

我有什么想法可以改进它吗?


EDIT1:

我希望它也适用于在其他类中创建的类:

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

>> MyAnotherClass.new

2 个答案:

答案 0 :(得分:2)

就个人而言,我没有看到按原样调用构造函数的问题,但如果您确实希望通过new调用它,则下面的getStaticCallingClassName可能对您有用。

以下是您使用它的方式:

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

有了这个,你可以打电话

obj = MyClass.new(input,arguments);

这里是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

答案 1 :(得分:0)

我可能会遗漏一些东西,但

出了什么问题
method1(MyClass(some_args))

? (我一直使用这种模式。)