Đây là đề nghị của tôi: tạo ra một phương pháp trong các lớp cha gọi add_dyn_prop
. Phương thức này được gọi trong các lớp con thay vì tạo một cách dependent property theo cách thông thường.
Ý tưởng là lớp cha kế thừa từ dynamicprops
và sử dụng addprop
đến add thuộc tính mới và đặt phương thức truy cập theo cách thủ công dựa trên tên của nó.
classdef klass < dynamicprops
methods (Access = protected)
function add_dyn_prop(obj, prop, init_val, isReadOnly)
% input arguments
narginchk(2,4);
if nargin < 3, init_val = []; end
if nargin < 4, isReadOnly = true; end
% create dynamic property
p = addprop(obj, prop);
% set initial value if present
obj.(prop) = init_val;
% define property accessor methods
% NOTE: this has to be a simple function_handle (@fun), not
% an anonymous function (@()..) to avoid infinite recursion
p.GetMethod = @get_method;
p.SetMethod = @set_method;
% nested getter/setter functions with closure
function set_method(obj, val)
if isReadOnly
ME = MException('MATLAB:class:SetProhibited', sprintf(...
'You cannot set the read-only property ''%s'' of %s', ...
prop, class(obj)));
throwAsCaller(ME);
end
obj.(prop) = val;
end
function val = get_method(obj)
val = obj.(prop);
end
end
end
end
bây giờ trong lớp con, thay vì xác định một tài sản phụ thuộc theo cách thông thường, chúng tôi sử dụng chức năng này được thừa hưởng mới trong các nhà xây dựng để xác định một tài sản năng động:
classdef subklass < klass
%properties (Dependent, SetAccess = private)
% name
%end
%methods
% function val = get.name(obj)
% val = 'Amro';
% end
%end
methods
function obj = subklass()
% call superclass constructor
obj = [email protected]();
% define new properties
add_dyn_prop(obj, 'name', 'Amro');
add_dyn_prop(obj, 'age', [], false)
end
end
end
Sản lượng:
>> o = subklass
o =
subklass with properties:
age: []
name: 'Amro'
>> o.age = 10
o =
subklass with properties:
age: 10
name: 'Amro'
>> o.name = 'xxx'
You cannot set the read-only property 'name' of subklass.
Tất nhiên bây giờ bạn có thể tùy chỉnh phương thức getter dựa trên tên thuộc tính như bạn dự định ban đầu.
EDIT:
Căn cứ ý kiến, xin vui lòng tìm thấy bên dưới một biến thể nhẹ của kỹ thuật tương tự đã thảo luận ở trên.
Ý tưởng là yêu cầu phân lớp để tạo thuộc tính (được định nghĩa là trừu tượng trong siêu lớp) chứa tên của các thuộc tính động mong muốn được tạo. Hàm khởi tạo của lớp cha sau đó sẽ tạo các thuộc tính động được chỉ định, thiết lập các phương thức truy cập của chúng thành các hàm chung (có thể tùy chỉnh hành vi của chúng dựa trên tên thuộc tính như bạn đã yêu cầu). Tôi đang sử dụng lại cùng chức năng add_dyn_prop
tôi đã đề cập trước đây.
Trong phân lớp, chúng tôi chỉ cần thực hiện thuộc tính trừu tượng dynamic_props
được thừa kế, được khởi tạo với danh sách tên (hoặc {}
nếu bạn không muốn tạo bất kỳ thuộc tính động nào). Ví dụ chúng ta viết:
classdef subklass < klass
properties (Access = protected)
dynamic_props = {'name', 'age'}
end
methods
function obj = subklass()
obj = [email protected]();
end
end
end
Các lớp cha cũng tương tự như những gì chúng tôi đã có trước khi trước đó, chỉ là bây giờ nó trách nhiệm của mình để gọi add_dyn_prop
trong constructor của nó cho mỗi tên thuộc tính:
classdef klass < dynamicprops % ConstructOnLoad
properties (Abstract, Access = protected)
dynamic_props
end
methods
function obj = klass()
assert(iscellstr(obj.dynamic_props), ...
'"dynamic_props" must be a cell array of strings.');
for i=1:numel(obj.dynamic_props)
obj.add_dyn_prop(obj.dynamic_props{i}, [], false);
end
end
end
methods (Access = private)
function add_dyn_prop(obj, prop, init_val, isReadOnly)
% input arguments
narginchk(2,4);
if nargin < 3, init_val = []; end
if nargin < 4, isReadOnly = true; end
% create dynamic property
p = addprop(obj, prop);
%p.Transient = true;
% set initial value if present
obj.(prop) = init_val;
% define property accessor methods
p.GetMethod = @get_method;
p.SetMethod = @set_method;
% nested getter/setter functions with closure
function set_method(obj,val)
if isReadOnly
ME = MException('MATLAB:class:SetProhibited', sprintf(...
'You cannot set the read-only property ''%s'' of %s', ...
prop, class(obj)));
throwAsCaller(ME);
end
obj.(prop) = val;
end
function val = get_method(obj)
val = obj.(prop);
end
end
end
end
Lưu ý: Tôi không sử dụng thuộc tính lớp ConstructOnLoad
hoặc thuộc tính bất động sản Transient
, vì tôi vẫn không chắc chắn cách chúng ảnh hưởng đến việc tải đối tượng từ tệp MAT đã lưu liên quan đến thuộc tính động.
>> o = subklass
o =
subklass with properties:
age: []
name: []
>> o.name = 'Amro'; o.age = 99
o =
subklass with properties:
age: 99
name: 'Amro'
Điều này gần nhất với những gì tôi đã kết thúc: Tôi có mỗi phân lớp xác định thuộc tính 'dynamic_props' và lớp cha (buộc phải' [ConstructOnLoad] (http://www.mathworks.com/help/matlab/matlab_oop/class -constructor-methods.html) ') khởi tạo tất cả chúng trong constructor của nó, thiết lập GetMethod thành một hàm ẩn danh chứa tên thuộc tính để cho phép thực thi chung. Một chút đơn giản hơn và được xác định rõ hơn cho người dùng, tôi nghĩ vậy. Tôi chỉ muốn Matlab có khả năng lập trình OO năng động hơn. Chúc mừng! –
@MattB .: Tôi đã đăng một triển khai thay thế dựa trên những gì bạn mô tả. – Amro
Yup, chính xác như thế nào tôi đã làm nó, ngoại trừ với Transient = true và constructOnLoad. Dường như nó hoạt động tốt với việc lưu và tải cho các mục đích của tôi. Tôi đã xem xét trả lời câu hỏi của riêng tôi, nhưng đã tìm ra câu hỏi của bạn là đủ gần. Bây giờ nó thực sự là! –