为什么MATLAB会尝试实例化抽象属性?

问题描述

在MATLAB中将类属性验证与抽象属性结合使用时,出现(对我而言)意外的行为。这是一个涉及三个类的简短示例:

classdef TestClass
    properties (Abstract)
        aprop (1,1) TestClassB
    end
end

classdef TestClassB
    methods
        function obj = TestClassB(a)
            disp(a);
        end
    end
end

classdef TestClassC < TestClass
    properties
        aprop
    end
end

然后,当尝试实例化TestClassC对象时,出现以下错误:

>> TestClassC()
Error defining property 'aprop' of class 'TestClass'. Unable to construct default
object of class TestClassB.

很明显,MATLAB试图实例化aprop中的抽象属性TestClass,然后由于aprop的类定义{{中缺少有效的零参数构造函数而失败。 1}}。我意识到零参数构造函数问题在理论上是可以解决的(尽管只有在您有权修改TestClassB的情况下),但是MATLAB完全实例化抽象属性的事实似乎很奇怪。维基百科有关抽象类型的文章的第一行从字面上指出:

...抽象类型是不能直接实例化的名词性类型系统中的类型...

也许这是MATLAB作为弱类型语言实现属性验证的唯一方法,但这是不幸的结果。

另一方面,如果TestClassB具有有效的零参数构造函数,但被定义为抽象的,则最终会陷入相同的陷阱,但错误略有不同:

TestClassB

这种行为是否有充分的理由?

编辑:

其他测试班观察结果

  1. 删除>> TestClassC() Error defining property 'aprop' of class 'TestClass'. Class TestClassB is abstract. Specify a default value for property aprop. 中的大小验证可消除该错误。显然,在没有有效的零参数构造函数的情况下,MATLAB初始化对象的空数组没有问题。注意:仅当TestClass不是抽象时,此功能才起作用。
  2. 如果TestClassB是抽象的,并且TestClassB在属性块中用TestClassC的具体子类初始化aprop ,则没有错误(假设具体子类具有有效的零参数构造函数)。注意:如果TestClassB是在aprop的构造函数中初始化的,则 not 为true。

激励例子

Car UML diagram

上面的UML图是将继承与组合相结合的典型示例。 TestClassCGenericCar是抽象类。 GenericEngine包含一个GenericCar,但是GenericEngine将其引擎指定为具体的Racecar(“ isa” V8)。不幸的是,这不能使用MATLAB中的属性验证来构造,因为MATLAB不允许您重新定义抽象属性的类,即使它是原始定义的子类也是如此。

假设您接受不能将GenericEngine中的engine定义为Racecar。即使这样,如果您没有在V8的属性块中为engine 提供一个初始值,则MATLAB会在创建Racecar对象时抛出错误,因为它将尝试使用抽象类型Racecar初始化engine。即使GenericEngine的构造函数将引擎初始化为Racecar对象也是如此。 这突出了属性验证和对象实例化之间的奇特联系。

解决方法

似乎应该回答两个问题:

1-“很明显,MATLAB试图实例化aprop中的抽象属性TestClass。那么为什么MATLAB试图实例化抽象属性?”

根据documentation(我强调):

您可以定义抽象属性的属性验证。验证适用于实现该属性的所有子类

MATLAB正在尝试实例化aprop中的属性TestClassC,该属性是TestClass concrete 子类。但是它使用与TestClass中使用的相同验证规则。 aprop的{​​{1}}属性不是抽象的。

2-“如果TestClassC ...被定义为抽象的,您最终将陷入同一陷阱...”

参考documentation

抽象类 —一个无法实例化的类,但它定义了子类使用的类组件。

TestClassB使用与TestClassC中相同的验证规则。它尝试实例化其属于TestClass类的aprop成员,但是TestClassB是抽象的并且无法实例化。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...