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

Time:11-10

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.

CodePudding user response:

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.

CodePudding user response:

Another approach is to use a validation function rather than a class/size constraint. I realise it doesn't feel quite as satisfactory, but it can be a useful approach. In this case

properties
    SomeFcn {mustBeA(SomeFcn, "function_handle")}
end
  • Related