4

是否可以定义一个 MATLAB 类,以便可以像调用任何其他函数一样调用此类中的对象?

IOW,我在问是否可以在 MATLAB 中编写类似于以下 Python 类的内容:

# define the class FxnClass
class FxnClass(object):
    def __init__(self, template):
        self.template = template

    def __call__(self, x, y, z):
        print self.template % locals()

# create an instance of FxnClass
f = FxnClass('x is %(x)r; y is %(y)r; z is %(z)r')

# call the instance of FxnClass
f(3, 'two', False)

...
[OUTPUT]
x is 3; y is 'two'; z is False

谢谢!

4

4 回答 4

5

我不知道,MATLAB是否直接支持你想要的,但MATLAB确实支持一流的功能;因此,闭包可能会提供一个可用的替代品,例如:

function f = count_call(msg)
    calls = 0;

    function current_count()
        disp(strcat(msg, num2str(calls)));
        calls = calls + 1;
    end

    f = @current_count;
end

在这种情况下,current_count关闭calls(和msg)。这样你就可以表达依赖于某些内部状态的函数。你会这样使用它:

g = count_call('number of calls: ') % returns a new function ("__init__")
g()                                 % "__call__"
于 2012-08-31T23:11:26.047 回答
4

如果不简单地在 Matlab 中创建一个 java 方法,我将有兴趣看看这是否可能。我知道您可以执行以下操作

classdef ExampleObject
    properties
        test;
    end
    methods
        function exampleObject = ExampleObject(inputTest)
            exampleObject.test=inputTest;
        end
        function f(exampleObject,funcInput)
            disp(funcInput+exampleObject.test);
        end
    end
end

>> e=ExampleObject(5);
>> f(e,10)
    15

但据我所知,如果你试图覆盖调用函数,你会遇到与 Matlab 的括号下标参考冲突subsref。您可以在此处找到显示如何覆盖它的参考资料,并且您也许可以让它做您想做的事……但这样做似乎不是一种好的形式。不确定 Matlab 将如何处理对对象(而不是函数)的调用而不会与此混淆。

于 2012-08-31T23:14:04.047 回答
4

一种方法是覆盖feval类的函数:

classdef FxnClass < handle
    properties
        template
    end
    methods
        function obj = FxnClass(t)
            obj.template = t;
        end

        function out = feval(obj, varargin)
            out = sprintf(obj.template, varargin{:});
        end
    end
end

这将用作:

>> f = FxnClass('x = %f, y = %s, z = %d');
>> feval(f, 3,'two',false)
ans =
x = 3.000000, y = two, z = 0

现在,如果您想提供额外的语法糖,您可以按照@Salain的建议重新定义subsref您的课程的功能。将以下内容添加到之前的类定义中:

classdef FxnClass < handle
    ...

    methods
        function out = subsref(obj, S)
            switch S(1).type
                case '.'
                    % call builtin subsref, so we dont break the dot notation
                    out = builtin('subsref', obj, S);
                case '()'
                    out = feval(obj, S.subs{:});
                case '{}'
                    error('Not a supported subscripted reference');
            end
        end
    end
end

现在你可以简单地写:

>> f = FxnClass('x = %f, y = %s, z = %d');
>> f(3,'two',false)
ans =
x = 3.000000, y = two, z = 0

就我个人而言,我不是特别喜欢覆盖subsreforsubsasgn函数。它们用于太多情况,有时很难让它们写出来。例如,以下所有内容最终都会subsref使用不同的输入调用该方法:

f(..)
f.template
f.template(..)
f(..).template
f(..).template(..)

还有end可能出现在索引中的关键字的情况,因此在某些情况下您可能还必须覆盖它。更不用说对象也可以连接成数组,这让事情变得更加复杂:

>> ff = [f,f];
>> ff(1)        % not what you expect!

也就是说,我认为@Frank建议在这种情况下使用带有闭包的嵌套函数更优雅:

function f = FxnClass(t)
    f = @call;
    function out = call(varargin)
        out = sprintf(t, varargin{:});
    end
end

像以前一样调用:

>> f = FxnClass('x = %f, y = %s, z = %d');
>> f(3, 'two', false)
于 2013-08-12T17:39:05.137 回答
1

如果您的意思是您希望一个类拥有一个您像普通函数一样使用的方法(例如,在 m 文件中定义),那么是的,Matlab 确实支持静态方法

静态方法独立于该类的任何实例运行,事实上,您甚至不需要实例化一个类来使用其静态方法。

但是, Matlab 不支持静态字段,因此您必须先实例化这样的类,然后在使用函数之前设置其字段(可能会使用这些字段,因为您在问这个问题)。

鉴于静态成员的限制,如Frank 所述,使用闭包可能会更好。

于 2012-08-31T23:16:01.107 回答