不幸的是,MATLAB 中数组的所有元素都必须属于同一类型。当您连接不同的类时,MATLAB 会尝试将它们全部转换为同一个类。
如果您已将您的一个类定义为低于或优于另一个(使用InferiorClasses属性或INFERIORTO / SUPERIORTO函数),则调用更高级类的方法。如果您没有指定类之间的关系,则这两个对象具有相同的优先级,并且 MATLAB 调用最左边的对象方法。这可能就是为什么arr = [b c];
创建一个 B 类数组并arr = [c b];
创建一个 C 类数组的原因。
选项 1:元胞数组
如果要在 object 上执行foo
为类 B 定义的方法b
,并在 object 上执行foo
为类 C 定义的方法c
,则可能必须使用元胞数组和函数CELLFUN。如果foo
不返回值,您可以执行以下操作:
arr = {b,c};
cellfun(@foo,arr); % Invoke foo on each element of the cell array
选项 2:陪审团操纵多态行为的乐趣
为了好玩,我想出了一个在技术上可行但有一些限制的潜在解决方案。为了说明这个想法,我整理了一些类似于您在问题中列出的示例类。这是抽象超类classA
:
classdef classA < hgsetget
properties
stuff
end
properties (Access = protected)
originalClass
end
methods
function foo(this)
disp('I am type A!');
if ~strcmp(class(this),this.originalClass)
this = feval(this.originalClass,this);
end
this.fooWorker;
end
end
methods (Abstract, Access = protected)
fooWorker(this);
end
end
这是子类的一个示例classB
(与处处替换classC
完全相同,反之亦然):B
C
classdef classB < classA
methods
function this = classB(obj)
switch class(obj)
case 'classB' % An object of classB was passed in
this = obj;
case 'classC' % Convert input from classC to classB
this.stuff = obj.stuff;
this.originalClass = obj.originalClass;
otherwise % Create a new object
this.stuff = obj;
this.originalClass = 'classB';
end
end
end
methods (Access = protected)
function fooWorker(this)
disp('...and type B!');
end
end
end
classB
和的构造函数classC
被设计成两个类可以相互转换。该属性originalClass
在创建时初始化,并指示对象的原始类是什么。如果一个对象从一个类转换为另一个类,该属性将保持不变。
在该foo
方法中,将传入对象的当前类与它的原始类进行检查。fooWorker
如果它们不同,则在调用方法之前首先将对象转换回其原始类。这是一个测试:
>> b = classB('hello'); % Create an instance of classB
>> c = classC([1 2 3]); % Create an instance of classC
>> b.foo % Invoke foo on b
I am type A!
...and type B!
>> c.foo % Invoke foo on c
I am type A!
...and type C!
>> arr = [b c] % Concatenate b and c, converting both to classB
arr =
1x2 classB handle
Properties:
stuff
Methods, Events, Superclasses
>> arr(1).foo % Invoke foo on element 1 (formerly b)
I am type A!
...and type B!
>> arr(2).foo % Invoke foo on element 2 (formerly c)
I am type A!
...and type C!
一个关键的限制(除了有点难看)是每个人都具有另一个人没有的属性的classB
情况。classC
在这种情况下,转换到另一个类然后再转换回来可能会导致这些属性丢失(即重置为它们的默认值)。但是,如果一个类是另一个类的子类,这样它就具有所有相同的属性和一些属性,那么就有一个解决方案。您可以将子类设置为优于超类(参见上面的讨论),这样两个类的连接对象将始终导致超类对象转换为子类。当在“多态”方法(foo
如上)中转换回来时,不会丢失任何对象数据。
我不知道这是一个多么可行的解决方案,但也许它至少会给你一些有趣的想法。;)