is it possible to add methods on the fly to matlab

2019-03-19 17:40发布

问题:

writing a subclass of dynamicprops allows to me to add properties dynamically to an object:

addprop(obj, 'new_prop')

this is great, but I would also love to create set / get functions for these properties on the fly. Or analysis functions that work on these dynamic properties.

My experience with Matlab has been so far, that once I create an instance of a class, adding new methods is not possible. That is very cumbersome, because my object may contain a lot of data, which I'll have to re-load everytime that I want to add a new method (because I have to do clear classes).

So is there a way to add methods on the fly?

回答1:

You cannot add methods like you add dynamic properties. However, there are two ways for implementing new methods during development that won't require you to re-load the data every time.

(1) I write standard methods as separate functions, and call them as myMethod(obj) during development. Once I'm sure they're stable, I add their signature into the class definition file - this requires a clear classes, of course, but it is a much delayed one, and from time to time you may have to shut down Matlab, anyway.

(2) With set/get methods, things are a little trickier. If you are using dynamicprops to add new properties, you can also specify their set/get methods, however (most likely, these methods/functions will want to receive the name of the property so that they know what to refer to):

addprop(obj,'new_prop');
prop = findprop(obj,'new_prop');
prop.SetMethod = @(obj,val)yourCustomSetMethod(obj,val,'new_prop')

EDIT

(2.1) Here's an example of how to set up a hidden property to store and retrieve results (based on jmlopez' answer). Obviously this can be improved a lot if you have a better idea what you're actually designing

classdef myDynamicClass < dynamicprops
    properties (Hidden)
        name %# class name
        store %# structure that stores the values of the dynamic properties
    end
    methods
        function self = myDynamicClass(clsname, varargin)
            % self = myDynamicClass(clsname, propname, type)
            % here type is a handle to a basic datatype.
            self.name_ = clsname;
            for i=1:2:length(varargin)
                key = varargin{i};
                addprop(self, key);
                prop = findprop(self, key);
                prop.SetMethod = @(obj,val)myDynamicClass.setMethod(obj,val,key);
                prop.GetMethod = @(obj)myDynamicClass.getMethod(obj,key);
            end
        end
        function out = classname(self)
            out = self.name_;
        end
    end
    methods (Static, Hidden) %# you may want to put these in a separate fcn instead
        function setMethod(self,val,key)
           %# have a generic test, for example, force nonempty double
           validateattributes(val,{'double'},{'nonempty'}); %# will error if not double or if empty

           %# store
           self.store.(key) = val;

        end
        function val = getMethod(self,key)
           %# check whether the property exists already, return NaN otherwise
           %# could also use this to load from file if the data is not supposed to be loaded on construction 
           if isfield(self.store,key)
              val = self.store.(key);
           else
              val = NaN;
           end
        end
    end
end


回答2:

I'm adding this answer because I think that this is not intuitive. At least not to myself at this moment. After finding this question I thought I had what I needed to be able to define the set/get methods for my dynamic class. All I wanted to achieve with this was something similar to what python does with its __setattr__ method. In any case, here is a continuation of the class made by @jonas a while ago with a few modifications to add the our custom set method.

classdef myDynamicClass < dynamicprops
    properties (Hidden)
        name_ %# class name
    end
    methods
        function self = myDynamicClass(clsname, varargin)
            % self = myDynamicClass(clsname, propname, type)
            % here type is a handle to a basic datatype.
            self.name_ = clsname;
            for i=1:2:length(varargin)
                key = varargin{i};
                addprop(self, key);
                prop = findprop(self, key);
                prop.SetMethod = makefunc(key, varargin{i+1});
            end
        end
        function out = classname(self)
            out = self.name_;
        end
    end
end

function h = makefunc(key, argtype)
    h = @newfunc;
    function newfunc(obj, val)
       obj.(key) = argtype(val); 
    end
end

With this class I'm defining the set method so that the parameter passed to the attribute is copied to the right type. To see what I mean consider the following usage:

>> p_int = myDynamicClass('Point', 'x', @int8, 'y', @int32);
>> p_int.x = 1000 

p_int = 

  myDynamicClass with properties:

    y: []
    x: 127

>> class(p_int.x)

ans =

int8

With this we have forced the x attribute to be an integer of 8 bits which can only hold integers from -128 to 127. Also notice how the class of each attribute gives us the intended type.



标签: oop matlab