如何在 matlab 包中使用静态工厂方法?

How do I use static factory method in matlab package?

我在 +mypackage\MyClass.m

下有以下 class 定义
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 放在包文件夹之外并删除“导入”语句时,它起作用了。
我做错了什么?

我认为您缺少的是当您导入静态方法时,您必须导入 class 名称和方法名称 (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

也就是说:不要在其自身的成员函数中创建对象 class!正如您所建议的,更好的选择是将工厂搬到不同的 class。如果你想制作一堆电锯,你永远不会去尝试设计一个带有按钮的电锯来构建电锯。你宁愿设计一个工厂来生产专门用来砍树的电锯。

一个'static factory'不是坏事。这实际上是一种非常常见的模式,尤其是在 C# 中。但是,工厂永远是自己的class。从另一个继承或扩展 class 的对象调用该方法(我不确定你甚至可以在 Matlab 中做...)如果不是致命的话,肯定会造成混淆。我也想不出你需要这样做的任何理由。事实上我不明白为什么 with_five() 应该是静态的

MATLAB 中有一些关于包和静态方法的古怪东西。

首先,包内的函数必须使用包名称来引用其他函数或同一包内的 classes(参见 here)。所以静态方法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);

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

>> 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

如果我们导入 class:

也是如此
>> 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 中,不再需要创建 class 的对象来使用其静态方法。