我有一个名为super的MATLAB类:
classdef super < handle
properties
aString = '';
end
methods
function obj = super(obj, value)
obj.aString = value;
end
function set.aString(obj, value)
obj.aString = value;
end
end
end
我想覆盖从'super'派生的子类中的set函数:
classdef sub < super
%// Property 'aString' is inherited from super
methods
function obj = sub(obj, value)
%// Must include call to super constructor otherwise MATLAB will by
%// default call constructor with no arguments but my super class
%// requires one argument in constructor. This call should probably
%// super set method. But I don't care.
obj = obj@super('');
%// Now that super constructor has returned, call sub overriding
%// set method
obj.aString = value;
end
function set.aString(obj, value)
obj.aString = value;
end
end
end
上面的代码给出了以下错误:
> Cannot define property 'aString' in class 'sub' because the property
> has already been defined in the superclass 'super'
将属性定义添加到'sub'会导致相同的错误。
我也尝试使用“Abstract”作为解决方法,但我没有成功,我定义了一个Abstract类:
classdef (Abstract) bloat < handle
properties (Abstract)
aString
end
end
然后尝试将'super'作为'膨胀'的孩子实施:
classdef super < bloat
%// Remainder of super code remains the same
我认为'sub'继承的时间不行,'aString'是“具体的”。然后,除了上述修改之外,我还尝试修改'sub'以在其类定义中包含'boat':
classdef sub < super & bloat
%// Remainder of super code remains the same
这也行不通。
我一直找不到任何特别说明的MATLAB文档:“你不能修改set和get方法”。
我希望我的语法不正确,但是从搜索开始我现在担心MATLAB不允许这样做(无论是作为错误还是设计)。
编辑: 我正在使用MATLAB 2013a
谢谢
答案 0 :(得分:3)
另一个解决方案是使set方法调用一个受保护的函数来执行赋值时需要的任何逻辑。这个受保护的方法当然可以在子类中重写。
虽然与上面的问题无关,但总是最好有一个接受零参数的构造函数以及当前的构造函数。看看我在这方面做出的改变。
classdef super < handle
properties
x = 1; % some property with a default value
end
methods
function obj = super(value)
% allow for zero-argument construction
if nargin > 0
obj.x = value;
end
end
function set.x(obj, value)
% call another function to check the value as desired,
% and possibly even update it using some computation
value = checkX(obj, value);
% set set the property using the validated value
% (only place we do assignment to avoid infinite recursion)
obj.x = value;
end
end
methods (Access = protected)
function value = checkX(obj, value)
% for example, we require that values be scalar positive
validateattributes(value, {'numeric'}, {'scalar','positive'});
end
end
end
classdef sub < super
methods
function obj = sub(value)
% set inherited property if requested
if nargin > 0
obj.x = value;
end
end
end
methods (Access = protected)
function value = checkX(obj, value)
% we could call superclass method to combine effect
value = checkX@super(obj, value);
% or override super-class logic (example: maximum value of 10)
value = min(value,10);
end
end
end
答案 1 :(得分:2)
您必须让set方法调用另一种方法,然后才能重载。这要求您使aString
依赖,并将其值存储在其他位置以避免无限递归。
classdef super < handle
properties (Dependent)
aString
end
properties (Hidden)
storeAString = '';
end
methods
function obj = super(obj, value)
obj.aString = value;
end
function set.aString(obj, value)
setString(obj,value);
end
function value = get.aString(obj)
value = obj.storeAString;
end
end
methods (Hidden)
function setString(obj,value)
%# this is the method you will be able to overload
obj.storeAString = value;
end
end
end
答案 2 :(得分:2)
首先,因为问题包括对Matlab文档的引用请求:
关于Property Access Methods州的Matlab文档(目前针对rev.2015a):
您只能定义属性访问方法:
- 对于具体属性(即非抽象属性)
- 在定义属性的类中(除非该属性在该类中是抽象的,在这种情况下,具体子类必须定义访问方法)。
所以看起来覆盖get / set-methods是不可能的。
第二次,这是另一个古怪的解决方法:可以创建一个属性observable,并且在通知程序中更改值。所以在超类中我们设置了SetObservable标志:
<强> super.m:
强>
classdef super < handle
properties (SetObservable)
aString;
end
methods
function obj = super(value)
obj.aString = value;
end
function set.aString(obj, value)
obj.aString = value;
end
end
end
在子类中,构造函数中引入了一个侦听器。它指向在分配属性值时调用的函数。然后,该函数检查该值(并在必要时更正/更改它)。
<强> sub.m:
强>
classdef sub < super
%// Property 'aString' is inherited from super
methods
function obj = sub(value)
%// Must include call to super constructor otherwise MATLAB will by
%// default call constructor with no arguments but my super class
%// requires one argument in constructor. This call should probably
%// super set method. But I don't care.
obj = obj@super('');
%// Now that super constructor has returned, call sub overriding
%// set method
obj.aString = value;
addlistener(obj, 'aString', 'PostSet',@obj.checkAString);
end
function checkAString(self, ~, ~)
if isempty(self.aString)
self.aString = 'was empty';
end;
end
end
end
如果你再运行
a_sub = sub('');
a_sub.aString = ''
你会得到:
a_sub =
sub with properties:
aString: 'was empty'
结果是。
然而,这也不是一个理想的解决方案。至少有这些缺点: