有没有Matlab中等效于Python的@classmethod的功能?

huangapple go评论67阅读模式
英文:

Is there a Matlab equivalent to Pythons @classmethod?

问题

在Matlab中,我想使用静态方法创建一个替代构造函数,并希望这个构造函数能够在子类中继承。我失败了,因为我无法在静态方法内部获取对调用类的引用。

考虑以下示例代码,其中有一个具有替代构造函数fromSomething的超类A:

classdef A

    properties
        a
    end
    
    methods
        function obj = A(a)
            if nargin
                obj.a = a;
            end
        end
    end

    methods(Static)

        function obj = fromSomething()
            obj = A(42);
        end
    end
end

可以通过调用A.fromSomething()来创建A的一个实例。

现在考虑子类B:

classdef B < A

    methods
        function someFunctionality(obj)
        end
    end

end

调用B.fromSomething()会返回一个类型为A的对象。这不是期望的行为。如何修改这段代码,使得B.fromSomething()可以返回一个类型为B的对象,并且代码复用尽可能少?

在Python中,可以使用@classmethod装饰器来实现:

from dataclasses import dataclass

@dataclass
class A:
    a : float

    @classmethod
    def from_something(cls):
        return cls(42)
    

class B(A):

    def some_functionality(self):
        ...

请注意,在Python代码中,B.from_something()将返回一个类型为B的对象。

我尝试过使用dbstack来获取当前类的类名:

...
        function obj = fromSomething()
            cls = currentClass();
            obj = feval(cls.Name, 42);
        end
...
function    [ cls, str ] = currentClass( )
% 参考自:https://nl.mathworks.com/matlabcentral/answers/77387-any-way-to-get-the-current-class
dbk = dbstack( 1, '-completenames' );
if isempty( dbk )
    str = 'base';
else
    str = dbk(1).name;
end
cac = regexp( str, '\.', 'split' );
switch  numel( cac )
    case 1
    case 2
        cls = meta.class.fromName( cac{1} );
        str = cac{2};
    case 3
    otherwise
end
end

然而,dbstack返回的是函数所定义的类(在本例中是A),而不是函数所调用的类(在本例中是调用B.fromSomething()时的B)。因此,B.fromSomething()仍然会返回一个类型为A的对象。

英文:

In Matlab, I want to create an alternative constructor using a static method, and I want this constructor to be able to inherit to subclasses. I fail to do so, because I cannot get a reference to the calling class inside a static method.

Consider this example code with superclass A that has an alternative constructor fromSomething:

classdef A

    properties
        a
    end
    
    methods
        function obj = A(a)
            if nargin
                obj.a = a;
            end
        end
    end

    methods(Static)

        function obj = fromSomething()
            obj = A(42);
        end
    end
end

An instance of A can be created by calling A.fromSomething().

Now consider subclass B:

classdef B &lt; A

    methods
        function someFunctionality(obj)
        end
    end

end

Calling B.fromSomething() gives an object of type A. That is not the desired behavior. How can this code be changed such that B.fromSomething() gives me an object of type B with minimal code re-use?

In Python, this would be done using a @classmethod decorator.

from dataclasses import dataclass

@dataclass
class A:
    a : float

    @classmethod
    def from_something(cls):
        return cls(42)
    

class B(A):

    def some_functionality(self):
        ...

Note that in the Python code B.from_something() will return an object of type B.

I've tried to obtain the class name of the current class using dbstack:

...
        function obj = fromSomething()
            cls = currentClass();
            obj = feval(cls.Name, 42);
        end
...
function    [ cls, str ] = currentClass( )
% Taken from https://nl.mathworks.com/matlabcentral/answers/77387-any-way-to-get-the-current-class
dbk = dbstack( 1, &#39;-completenames&#39; );
if isempty( dbk )
    str = &#39;base&#39;;
else
    str = dbk(1).name;
end
cac = regexp( str, &#39;\.&#39;, &#39;split&#39; );
switch  numel( cac )
    case 1
    case 2
        cls = meta.class.fromName( cac{1} );
        str = cac{2};
    case 3
    otherwise
end
end

However, dbstack returns the class that the function is defined on (in this case: A), rather than the class the function is called on (in this case, B when calling B.fromSomething()). As a result B.fromSomething() will still return an object of type A.

答案1

得分: 2

根据文档,我会说MATLAB似乎没有类方法:

https://uk.mathworks.com/help/matlab/matlab_oop/how-to-use-methods.html

事实上,这在大多数编程语言中都不是常见的方法类型。

英文:

I would say that reading from the docs, MATLAB does not seem to have class methods:

https://uk.mathworks.com/help/matlab/matlab_oop/how-to-use-methods.html

In fact this is not a common type of method in most programming languages.

答案2

得分: 2

@staticmethod 是一种非常具有 Python 风格的东西,你需要它是因为 Python 不支持函数重载,而且不容易模拟它。在 MATLAB 中,一个函数通常可以有多个签名,根据给定的输入执行不同的操作。

我理解你的用例是根据特定输入 something 构建一个对象:A.fromSomething(something),而不是一个普通的 A()A.fromFoo(foo)

在 MATLAB 中,所有这些情况通常由同一个构造函数处理。你可以让它看起来像这样:

classdef A
   % ...
   methods
      function obj = A(arg)
         if nargin == 0
            % 情况 A()
         else
            if isa(arg, 'Something')
               % 情况 A(something)
            elseif isa(arg, 'Foo')
               % 情况 A(foo)
            else
               error('非法输入')
            end
         end
      end
   end
end
英文:

@staticmethod is a very Pythony thing, and you need it because Python doesn't do function overloading, and doesn't make it easy to simulate it. In MATLAB it is quite common for a function to have multiple signatures, and do different things depending on which inputs are given.

Your use case, I presume, is to construct an object given a specific input something: A.fromSomething(something), as opposed to a plain A(), or a A.fromFoo(foo).

In MATLAB all these cases are typically handled by the same constructor. You can make it look like this:

classdef A
   % ...
   methods
      function obj = A(arg)
         if nargin == 0
            % case A()
         else
            if isa(arg, &#39;Something&#39;)
               % case A(something)
            elseif isa(arg, &#39;Foo&#39;)
               % case A(foo)
            else
               error(&#39;Illegal input&#39;)
            end
         end
      end
   end
end

huangapple
  • 本文由 发表于 2023年7月6日 19:32:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76628381.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定