matlaboopinterfacefunction-handle

What is the correct way to declare a property of type function_handle in an abstract class in MATLAB?


I'm trying to create an interface that other classes in MATLAB will inherit. This interface has a property that holds a function_handle value. The problem I'm running into is that, upon instantiating a concrete class that inherits from this class, I get the message: Error defining property 'MyFuncHandle' of class 'IMyInterfaceClass'. Unable to construct default object of class function_handle.

The interface class looks something like this:

classdef (Abstract) IMyInterfaceClass < handle
    properties (Abstract)
        MyFuncHandle(1,1) function_handle
    end

    methods (Abstract, Access = public)
        % Some abstract methods declared here
    end
end

With another class inheriting the interface like this:

classdef (Abstract) MyClassThatInheritsTheInterface < IMyInterfaceClass & SomeOtherAbstractClass
    properties
        MyFuncHandle
    end

    methods (Abstract)
        % Some abstract methods declared here
    end

    methods
        function this = MyClassThatInheritsTheInterface()
            this@SomeOtherAbstractClass();
        end

        % Some concrete methods declared here
    end
end

And, ultimately, a concrete subclass that inherits from MyClassThatInheritsTheInterface.

I've tried changing the property declaration in IMyInterfaceClass to:

    properties (Abstract)
        MyFuncHandle(1,1) function_handle = function_handle.empty
    end

But, that doesn't work. I've also tried just setting it to a default value like this:

    properties (Abstract)
        MyFuncHandle(1,1) function_handle = @ode15s
    end

That doesn't work either.

Is there any way to get this to work, while keeping the type-checking on MyFuncHandle in IMyInterfaceClass? Obviously, getting rid of the type check and leaving it as a duck-typed property would eliminate the error but would not ensure that the value in the property is a function_handle.


Solution

  • I think we can distil the example down a bit to fix this issue

    Abstract super class

    classdef (Abstract) IMyInterfaceClass < handle
        properties 
            MyFuncHandle(1,1) function_handle = @(varargin) disp([])
        end
        methods (Abstract, Access = public)
            % Some abstract methods declared here
        end
    end
    

    Concrete class which inherits the abstract class

    classdef MyClassThatInheritsTheInterface < IMyInterfaceClass
        properties
            % Subclass properties
        end
        methods
            function this = MyClassThatInheritsTheInterface()
                this@IMyInterfaceClass();
            end
            % Some concrete methods declared here
        end
    end
    

    These are pretty much lifted from your example, except I've skipped the 2nd layer of abstraction and just used one abstract superclass. The following points should still be applicable.

    Note that MyFuncHandle should only be specified in the abstract super class.

    Also function_handle.empty is, as you might expect, empty. However, you want a 1x1 function handle per your property specification. The simplest "do-nothing" function I know of which satisfies this is @(varargin) disp([]) which accepts any inputs and displays nothing. You could of course use something which instead throws an error if it's not been overwritten

    @(varargin) error( 'MyFuncHandle has not been defined' );
    

    Now you can do a = MyClassThatInheritsTheInterface(); and you will see that a.MyFuncHandle is correctly initialised.

    Perhaps the key here is that at no point does this try to class something as both an Abstract property, whilst also giving it a value which is not consistent with it being abstract.