2

我在 +mypackage\MyClass.m 下有以下类定义

classdef MyClass  
    properties
        num
    end
    
    methods (Static)
        function obj = with_five()
            obj = MyClass(5);
        end
    end
    
    methods
        function obj = MyClass(num)
            obj.num = num;
        end
    end
end

我使用 with_five() 作为静态工厂方法。
以下脚本应创建两个对象。

import mypackage.MyClass
class_test1 = MyClass(5);
class_test2 = MyClass.with_five();

class_test1 已创建。
对于 class_test2 它说:

Error using MyClass.with_five
Method 'with_five' is not defined for class 'MyClass' or is removed from MATLAB's search path.
Error in Testpackage (line 4)
class_test2 = MyClass.with_five();

当我将 MyClass.m 放在包文件夹之外并删除“import”语句时,它可以工作。
我究竟做错了什么?

4

2 回答 2

3

MATLAB 中有一些带有包和静态方法的东西。

首先,包中的函数必须使用包名来引用同一包中的其他函数或类(参见此处)。所以静态方法mypackage.MyClass.with_five()必须声明如下:

    methods (Static)
        function obj = with_five()
            obj = mypackage.MyClass(5);
        end
    end

没有这个,我看到:

>> mypackage.MyClass.with_five
Undefined function or variable 'MyClass'.

Error in mypackage.MyClass.with_five (line 8)
            obj = MyClass(5);

其次,在创建类的对象之前,不会加载静态类方法(至少是包内类的方法)。所以我们需要先调用类的构造函数:

>> clear classes
>> mypackage.MyClass.with_five
Undefined variable "mypackage" or class "mypackage.MyClass.with_five".
 
>> mypackage.MyClass(1);
>> mypackage.MyClass.with_five

ans = 

  MyClass with properties:

    num: 5

如果我们导入类也是如此:

>> clear classes
>> import mypackage.MyClass
>> MyClass.with_five
Undefined variable "mypackage" or class "mypackage.MyClass.with_five".
 
>> MyClass(3);
>> MyClass.with_five

ans = 

  MyClass with properties:

    num: 5

第二点在 R2017a 中是正确的(生成上述输出的地方),但在 R2021a 中不再正确。我不知道这是在哪个 MATLAB 版本中修复的,但在 R2021a 中,不再需要创建类的对象来使用其静态方法。

于 2021-07-15T04:35:04.640 回答
0

我认为您缺少的是,当您导入静态方法时,您必须导入类名和方法名https://au.mathworks.com/help/matlab/matlab_oop/importing-classes.html )

这有效:

classdef MyClass  
    properties
        num
    end
    
    methods (Static)
        function obj = with_five()
            obj = MyClass(5);
        end
    end
    
    methods
        function obj = MyClass(num)
            obj.num = num;
        end
    end
end

然后执行以下操作:

>> import MyClass.with_five
>> x = with_five

输出:

x = 

  MyClass with properties:

    num: 5

话虽这么说:不要在其自己的类的成员函数中创建对象!正如您所建议的,更好的选择是将工厂转移到不同的类别。如果你想制造一堆电锯,你永远不会去尝试设计一个上面有一个按钮来制造电锯的电锯。您宁愿设计一家可以生产用于砍伐树木的电锯的工厂。

“静态工厂”并不是一件坏事。这实际上是一种非常常见的模式,尤其是在 C# 中。但是,工厂始终是自己的类。从继承或扩展该类的另一个对象调用该方法(我不确定您甚至可以在 Matlab 中做到这一点......)如果不是致命的话,肯定会令人困惑。我也想不出你需要这样做的任何理由。事实上我不明白为什么with_five()应该是静态的

于 2021-07-15T00:55:12.787 回答