Search code examples
matlaboopmatlab-class

How to make a member public in an class object created using MATLAB Class folder?


I'm trying to reuse a package in which all classes are written using Class folder i.e all methods are files inside a folder @myclassname. I would like to read the members of the class object. In normal classdef classes, declaring a property public solves the problem. In my case, I didn't find any solutions and I don't want to rewrite the whole package.

Minimal example explaining my problem: simple class: \MatlabPath\@mytestclass\mytestclass.m

%myconstructor
function res =mytestclass()
st.a=1;
res=class(st,mfilename);
end

Current behavior:

>> obj=mytestclass();
>> obj.a
Access to an object's fields is only permitted within its methods.

Desired:

>> obj=mytestclass();
>> obj.a
ans =
1

Thank you


Solution

  • I know you don't want to rewrite the full package but if property access is important you might prefer that to the actual solution.

    In the first MATLAB OOP classes, organised as you indicated (all methods in one folder), the programmer had to code their own subsref and subsasgn methods if they wanted customized access to their class properties.

    I must say I did play a bit with it but quickly gave up as construction of simple classes was extremely tedious. MATLAB probably picked up on that and in later release introduced the new Classdef model. Despite still having a few quicks (due to MATLAB passing almost everything by value), this Classdef model is infinitely more convenient than the old formula.

    If you want to stick with the old model, I can give you a minimalist example which will give you the desired behaviour. If you are only interested in exposing a few properties you can just replicate that a few times. If you plan to have all the properties of your package exposed, then I guarantee you that rewriting the package will be less effort than applying my solution to an extensive existing code base.

    So in your folder : \MatlabPath\@mytestclass\, you now need two files:

    mytestclass.m (I added a couple of different properties for example)

    function res =mytestclass()
        st.scalar = 1 ;
        st.array  = [1 2 3] ;
        st.cellarray = {'1' '2' '3'} ;
        res=class(st,mfilename);
    end
    

    and your own subsref.m:

    function out = subsref(obj,S)
    
    thisS = S(1) ;
    
    if strcmp(thisS.type , '.')
        out = obj.(thisS.subs) ;
        
    elseif strcmp(thisS.type , '{}')
        % You might have to code this case too
        
    elseif strcmp(thisS.type , '{}')
        % You might have to code this case too
    end
    
    % recursive call if the struct S has more than one element
    if numel(S) > 1
        S(1) = [] ;
        out = subsref(out,S) ;
    end
    
    end
    

    Armed with that, you can now access your properties:

    >> obj.scalar
    ans =
         1
    >> obj.array
    ans =
         1     2     3
    >> obj.cellarray
    ans = 
        '1'    '2'    '3'
    

    This minimal subsref works for indexing into the arrays as well:

    >> obj.array(2:end)
    ans =
         2     3
    >> obj.cellarray(2)
    ans = 
        '2'
    

    And it also works for assignment:

    >> obj.scalar = 125 ;
    >> obj.scalar
    ans =
       125
    >> obj.array(2:end) = [8 9] ;
    >> obj.array
    ans =
         1     8     9
    

    Keep in mind that this is a minimal example, some property type might not respond well to these simple cases, in which case you will have to add specific code to handle each particular case.