简体   繁体   中英

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?

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.

I think what you are missing is the fact that when you import a static method, you have to import the class name and the method name ( https://au.mathworks.com/help/matlab/matlab_oop/importing-classes.html )

This works:

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

Then do the following:

>> import MyClass.with_five
>> x = with_five

Output:

x = 

  MyClass with properties:

    num: 5

That being said: don't create an object in a member function of its own class! As you suggest, a better choice is to move the factory to a different class. If you wanted to make a bunch of chainsaws, you would never go about trying to design a chainsaw that has a button on it that builds chainsaws. You would rather design a factory that can produce chainsaws that are designed to cut down trees.

A 'static factory' is not a bad thing. This is actually a pretty common pattern especially in C#. However, the factory is always its own class. Calling that method from another object that inherits from or extends that class (which I'm not sure you can even do in Matlab...) would most certainly be confusing if not deadly. I also can't think of any reason you would ever need to do this. In fact I don't understand why with_five() should be static at all

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM