matlaboopstatic-factory

How do I use static factory method in matlab package?


I have following class definition under +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

I use with_five() as a static factory method.
Following script should create two objects.

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

class_test1 has been created.
For class_test2 it says:

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();

When I put MyClass.m outside of a package folder and remove the "import" statement, it works.
What am I doing wrong?


Solution

  • There are several wonky things in MATLAB with packages and with static methods.

    First, functions within a package must use the package name to reference other functions or classes within the same package (see here). So the static method mypackage.MyClass.with_five() must be declared as follows:

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

    Without this, I see:

    >> mypackage.MyClass.with_five
    Undefined function or variable 'MyClass'.
    
    Error in mypackage.MyClass.with_five (line 8)
                obj = MyClass(5);
    

    Second, static class methods (at least the ones for classes inside packages) are not loaded until an object of the class is created. So we need to call the class constructor first:

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

    The same is true if we import the 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
    

    This second point was true in R2017a (where the outputs above were generated), but is no longer true in R2021a. I don't know in which release of MATLAB this was fixed, but in R2021a it is no longer necessary to create an object of a class to use its static method.