在本页中

属性阴影和覆盖语义

属性阴影

默认情况下,属性可以阴影化:你在派生的 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 propertyItem 已被 Building 上新引入的 rotation 属性所遮蔽。当把这个对象传递给处理 Items 的通用函数时,函数会尝试读取对象的旋转属性,并期望得到Item 定义的 real 类型的属性。相反,它得到的是一个字符串,从而导致意想不到的结果。

这也是 QML 工具的一个障碍。它很少能在不执行操作代码的情况下确定属性的类型。这是因为持有属性的对象往往是派生类型。

因此,这不仅会让用户感到困惑,导致意想不到的难以发现的错误,而且还会阻止工具生成更优化的代码。

为了解决这个问题,我们引入了finaloverridevirtual 关键字以及附加的警告和错误。它们的目的是帮助用户避免意外的阴影,并在属性确实需要替换基础类型中的属性的罕见情况下提供明确的机制。我们将这种显式阴影称为覆盖

注意: 如上所述,阴影通常是偶然的,而且通常会导致含糊不清和难以诊断的行为,因此,在可能的情况下,我们更倾向于使用唯一命名的属性,而不是阴影和覆盖。

虚拟、覆盖、最终关键字

  • 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.