不幸的是,MATLAB中数组的所有元素必须属于同一类型。当您连接不同的类时,MATLAB将尝试将它们全部转换为同一个类。
如果您已将某个类定义为低于或高于另一个类(使用InferiorClasses属性或INFERIORTO / SUPERIORTO函数),那么调用更优越的类。如果尚未指定类之间的关系,则两个对象具有相同的优先级,MATLAB调用最左侧的对象方法。这可能是arr = [b c];创建一个B类数组,arr = [c b];创建一个C类数组的原因。
选项1:单元阵列
如果要执行在对象foo上为类B定义的b方法,并执行在对象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各自具有另一个不具有的属性的情况。在这种情况下,转换到另一个类然后转换回来可能会导致这些属性丢失(即重置为其默认值)。但是,如果一个类是另一个类的子类,那么它具有所有相同的属性和thensome,那么就有一个解决方案。您可以将子类设置为优于超类(参见上面的讨论),这样两个类的连接对象总是会导致超类对象转换为子类。在“多态”方法(如上面的foo)中转换回来时,不会丢失任何对象数据。
我不知道解决方案是多么可行,但也许它至少会给你一些有趣的想法。 ;)