属性阴影和覆盖语义
属性阴影
默认情况下,属性可以阴影化:你在派生的 QML 类型中重新声明一个属性,可能使用新的类型和新的属性。结果将是两个同名的属性,在任何给定的上下文中只有一个是可访问的。这很少是你想要的。这往往是偶然的,而且大多数情况下效果会非常混乱。
请看下面的例子:假设我们有一个 Building 类型,用于用 QML 编写的建筑可视化软件:
// Building.qml import QtQuick Item { property int floors property string rotation // like CSS rotate, "-120deg" property date constructionDate }
Building 是一个 Item,因为它继承自 Item,但重要的是,rotation property ,Item 已被 Building 上新引入的 rotation 属性所遮蔽。当把这个对象传递给处理 Items 的通用函数时,函数会尝试读取对象的旋转属性,并期望得到Item 定义的 real 类型的属性。相反,它得到的是一个字符串,从而导致意想不到的结果。
这也是 QML 工具的一个障碍。它很少能在不执行操作代码的情况下确定属性的类型。这是因为持有属性的对象往往是派生类型。
因此,这不仅会让用户感到困惑,导致意想不到的难以发现的错误,而且还会阻止工具生成更优化的代码。
为了解决这个问题,我们引入了final 、override 和virtual 关键字以及附加的警告和错误。它们的目的是帮助用户避免意外的阴影,并在属性确实需要替换基础类型中的属性的罕见情况下提供明确的机制。我们将这种显式阴影称为覆盖。
注意: 如上所述,阴影通常是偶然的,而且通常会导致含糊不清和难以诊断的行为,因此,在可能的情况下,我们更倾向于使用唯一命名的属性,而不是阴影和覆盖。
虚拟、覆盖、最终关键字
final关键字将此声明标记为最终声明。它可以覆盖基本类型的属性,但派生类型不能覆盖或阴影。这有助于防止意外阴影,并允许 QML 工具生成更优化的代码。override关键字表示该属性有意覆盖基础类型的虚拟属性。覆盖另一个属性的属性不需要标记为virtual。它会自动继承被覆盖属性的虚拟性。如果原始属性是虚拟的,覆盖的属性也是虚拟的。如果不是,则覆盖无效,并会产生错误。virtual关键字明确表示该属性将被覆盖。在覆盖属性上添加virtual没有任何作用,请参见override。
这就是它们的实际使用方法:
// Base.qml QtObject { virtual property int a virtual property int b virtual property var c property var d } // DerivedMixed.qml Base { override property var a // fine: overrides property "a" of a Base type final readonly property int b // fine: overrides property "c" of a Base type; can't be overriden any more } // DerivedDerivedMixed.qml DerivedMixed { virtual property int a // warning: overrides virtual property, but lacks "override" or "final" override property int a // fine: overrides a property "a" of a DerivedMixed type; final property int a // fine: overrides a property "a" of a DerivedMixed type; can't be overriden any more virtual property int b // error: can't override a final property override property int b // error: can't override a final property final property int b // error: can't override a final property final property int c // fine: overrides property "c" of a Base type; can't be overriden any more override property int d // error: overrides a property that is not marked virtual }
注: 最好使用final override
这里还有一份关于 `virtual`、`override` 和 `final` 组合的详尽列表,以供参考:
// Base.qml QtObject { property int a // fine: declaring a property virtual property int b // fine: declaring a property that is intended to be overriden final property int c // fine: declaring a property that can't be overriden override property int d // error: does not override anything virtual override property int d // parser error: remove override virtual final property int d // parser error: virtual and final are mutually exclusive } // Derived.qml Base { property int a // warning: overrides a property that is not marked virtual property int b // warning: overrides a virtual property, but lacks "override" or "final" property int c // error: can't override a final property } // DerivedVirtual.qml Base { virtual property int a // warning: overrides a property that is not marked virtual virtual property int b // warning: overrides a virtual property, but lacks "override" or "final" virtual property int c // error: can't override a final property } // DerivedFinal.qml Base { final property int a // warning: overrides a property that is not marked virtual final property int b // fine: overrides a property "b" from the Base type; can't be overriden any more final property int c // error: can't override a final property } // DerivedOverride.qml Base { override property int a // error: overrides a property that is not marked virtual override property int b // fine: overrides a property "b" from the Base type override property int c // error: can't override a final property override final property int d // parser error: remove override }
注: 大多数警告将来都会变成错误,出于向后兼容性的考虑,我们暂时还不能把它们变成错误。
注: 这些语义由 QmlEngine 执行。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.