0

我正在编写一个类定义,它在设置某些属性时使用侦听器来修改对象。像这样:

classdef MyObject < handle
    properties (SetObservable)
        orientation = 'h'; % h = horizontal, v = vertical, o = other
        length
        width
    end
    methods
        % Constructor
        function mo = MyObject(o)
            mo.orientation = o;
            addlistener(mo, 'orientation', 'PreSet', @mo.changeOrientation);
        end

        % Change Orientation Listener
        function changeOrientation(mo, src, evnt)
            celldisp(src);
            celldisp(evnt);
            % I want a way to access newor here
            if mo.orientation == 'h' && newor == 'o'
                tempw = mo.width
                mo.width = mo.length
                mo.length = tempw;
            end
        end

        % Setter
        function set.orientation(mo, newor)
            mo.orientation = newor;
        end
    end
end

我希望能够在设置方向时使用变量 newor。如何将新的方向变量传递给 changeOrientation 方法?

我想避免将 的内容移动changeOrientationset.orientation方法中,因为 Matlab 抱怨属性(长度和宽度)可能没有被初始化。

EDIT 长度不依赖于方向。当方向改变时,我只需要交换长度和宽度。在其他情况下,用户应该能够将长度或宽度设置为任何正值。

4

2 回答 2

1

您不能这样做,因为 PreSet 侦听器就是一个侦听器。传递给侦听器回调的数据永远不会返回对象,并且在侦听器中修改其值没有任何影响。

使用 PreSet 侦听器的目的是在属性更改之前获取属性的值,而不是在实际分配之前修改任何值。

在您发布的代码中,我可能会在set.orientation您的类方法中对方向进行任何验证/修改。

function updateLength(mo)
    % Change mo.length here and others based on mo.orientation
end

function set.orientation(mo, newor)
    % validate newor
    if dovalidation(newor)
        mo.orientation = newor;
    else
        error('invalid!');
    end

    % Now trigger a "callback"
    mo.updateDependentVariables()
end

编辑

根据您的评论,解决此问题的更好方法可能是创建length一个 shadow 属性length_来保存用户分配给的值length。当用户请求它的值时,length它可以返回这个存储的值(如果方向 == 'v')或width(如果方向 == 'h')

classdef MyObject
    properties (Dependent)
        length   % Can be either `width_` or `length_`
        width    % Can be either `width_` or `length_`
    end

    properties
        orientation
    end

    properties (Access = 'protected')
        length_ = 12
        width_ = 10
    end

    methods
        function mo = MyObject(o)
            mo.orientation = o;
        end

        function set.orientation(mo, newor)
            % If the user supplies an "o" flip the orientation
            if strcmpi(newor, 'o')
                if strcmpi(mo.orientation, 'v')
                    newor = 'h';
                else
                    newor = 'v';
                end
            end

            mo.orientation = newor;
        end    

        function set.length(mo, value)
            if strcmpi(mo.orientation, 'h')
                self.length_ = value;
            else
                self.width_ = value;
            end
        end

        function set.width(mo, value)
            if strcmpi(mo.orientation, 'h')
                self.width_ = value;
            else
                self.length_ = value;
            end
        end

        function res = get.width(mo)
            switch lower(mo.orientation)
                case 'h'
                    res = mo.width_;
                case 'v'
                    res = mo.length_;
                otherwise
                    error('Invalid orientation');
            end
        end

        function res = get.length(mo)
            switch lower(mo.orientation)
                case 'h'
                    res = mo.length_;
                case 'v'
                    res = mo.width_;
                otherwise
                    error('Invalid orientation');
            end
        end     
    end
end

这样您就不必length在更改方向时显式更新。

附带说明一下,我不会length其用作属性,因为它与内置函数有点混淆length

于 2016-03-09T20:53:42.837 回答
0

你不需要额外的监听器。这就是自定义 setter / getter 方法的用途。在您的示例中使用set.orientation方法没有任何意义,除了无论如何都会发生的分配之外,它什么都不做。相反,使用此方法进行额外调用changeOrientation

classdef MyObject < handle
    properties (SetObservable)
        orientation = 'h'; % h = horizontal, v = vertical
    end
    methods
        % Constructor
        function mo = MyObject(o)
            mo.orientation = o;
        end

        % Change Orientation Listener
        function changeOrientation(mo, newor)
            % Use newor here!
        end

        % Setter
        function set.orientation(mo, newor)
            mo.changeOrientation(newor);
            mo.orientation = newor;
        end
    end
end
于 2016-03-09T20:56:19.360 回答