我正在创建一个工具箱,我想动态地将特定属性添加到类的实例,同时限制用户添加属性的能力。
我正在考虑对象类的基线功能,称为模型。每个模型都可以用附加功能进行装饰,例如 Bootstrap CI、排列测试等。
我希望将附加功能附加到对象实例。据我了解,使用装饰器模式会在其中存储模型的实例,但是如果我有多个装饰器作用于同一个对象,我不确定该怎么办 - 例如引导 CI 和排列测试。我认为仅通过调用为模型类定义的方法向对象添加动态属性将是最好的选择,但我不知道如何编程,同时使用户无法向对象添加属性对象。
最佳答案
当我想实现与标题相同的功能时,这个相对较旧的问题作为搜索结果弹出:使用动态属性但限制 addprop
的使用。尽管我同意评论和之前的答案,即通常应该避免动态属性,但我认为我能够找到满足原始问题的答案。
我的想法是有一个继承自 dynamicprops
的类和 modifies (即覆盖)继承的 addprop
功能。这样,您可以添加一个条件,即对 addprop
的调用必须来自特定函数(使用 dbstack
),或者您可以向调用添加一个私有(private)逻辑“锁定”属性,该属性可以内部访问以允许或禁止使用修改后的 addprop
函数。然后可以将更改此“锁”的状态并添加新属性分组到只能在内部访问的单独函数中。以下是这两种方法的两个简短示例:
Model.m(堆栈条件)
classdef Model < dynamicprops
methods (Access = public)
function obj = Model()
obj@dynamicprops();
obj.internalAddProperty("Test", 5);
end
function storeSumAsProperty(obj, a, b)
obj.internalAddProperty("Sum", a + b);
end
function addprop(obj, prop)
% The caller of this function must be 'Model.internalAddProperty'
[ST,I] = dbstack(1);
if isempty(ST) || ~strcmp(ST(I).name, [mfilename(), '.internalAddProperty'])
error("Adding a new property to this instance is not allowed.");
end
% Call original implementation if not locked
addprop@dynamicprops(obj, prop);
end
end
methods (Access = protected)
function internalAddProperty(obj, prop, value)
% The only thing this function does is add a new "layer" to the call stack
obj.addprop(prop);
obj.(prop) = value;
end
end
end
Model.m(具有“锁定”属性)
classdef Model < dynamicprops
properties (Access = private)
propertiesLocked (1,1) logical = false
end
methods (Access = public)
function obj = Model()
obj@dynamicprops();
obj.addprop("Test");
obj.Test = 5;
obj.propertiesLocked = true;
end
function storeSumAsProperty(obj, a, b)
obj.internalAddProperty("Sum", a + b);
end
function addprop(obj, prop)
if obj.propertiesLocked
error("Adding a new property to this instance is not allowed.");
end
% Call original implementation if not locked
addprop@dynamicprops(obj, prop);
end
end
methods (Access = protected)
function internalAddProperty(obj, prop, value)
obj.propertiesLocked = false;
obj.addprop(prop);
obj.propertiesLocked = true;
obj.(prop) = value;
end
end
end
当使用 Matlab 命令窗口中提供的两个类中的任何一个时,我们会得到以下行为:
>> m = Model()
m =
Model with properties:
Test: 5
>> m.storeSumAsProperty(5, 10)
>> m
m =
Model with properties:
Sum: 15
Test: 5
>> m.addprop("NewProp")
Error using Model/addprop
Adding a new property to this instance is not allowed.
>> addprop(m, "NewProp")
Error using Model/addprop
Adding a new property to this instance is not allowed.
这两种方法都可以创建子类。任何子类都可以使用函数internalAddProperty
来添加动态属性。如果子类不能添加动态属性,则函数 internalAddProperty
的访问修饰符必须设置为 private
。
最后一点:因为第二种方法的函数internalAddProperty
的内容(即解锁,调用addprop
,然后再次锁定)不是自动执行的,在某些非常特定的情况下可能会出现竞争条件问题。
关于限制访问 addprop 的 Matlab 动态属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32478852/