このページでは

プロパティのシャドウイングとオーバーライドセマンティクス

プロパティのシャドウイング

デフォルトでは、プロパティはシャドウイングされます:派生したQMLの型の中でプロパティを再宣言します。その結果、同じ名前のプロパティが2つ存在することになります。このようなことが起こることはほとんどありません。多くの場合、これは偶発的なものであり、ほとんどの場合、その影響は非常に混乱させるものです。

QMLで書かれた建築ビジュアライゼーション・ソフトウェアで使われるBuildingという型があるとします:

// Building.qml
import QtQuick

Item {
    property int floors
    property string rotation // like CSS rotate, "-120deg"
    property date constructionDate
}

BuildingはItemを継承しているのでItemですが、重要なのは、Itemrotation property が、新しく導入されたBuildingのrotationプロパティによって影が薄くなっていることです。このオブジェクトをItemを扱うジェネリック関数に渡すと、その関数はオブジェクトのrotationプロパティを読み取ろうとし、Item で定義されているreal型のプロパティが返ってくると期待します。その代わりに文字列が返され、予期しない結果を招きます。

これはQMLツールにとっても障害となります。QMLツールは、プロパティを操作するコードを実行することなく、プロパティの型を確実に決定できることはほとんどありません。なぜなら、プロパティを保持するオブジェクトが派生型であることが多いからです。

そのため、ユーザーを混乱させ、予期せぬ見つけにくいバグを引き起こすだけでなく、ツーリングがより最適化されたコードを生成することもできません。

この問題に対処するため、finaloverridevirtual のキーワードが、追加の警告とエラーとともに導入されました。これらのキーワードの目的は、ユーザが偶発的なシャドウイングを回避できるようにすることと、プロパティが本当に基本型のプロパティを置き換える必要があるまれなケースに対して明示的なメカニズムを提供することです。このような明示的なシャドウイングをオーバーライドと呼ぶ。

注: 上記で説明したように、シャドウイングは偶発的であることが多く、通常はあいまいで診断しにくい動作につながります。可能な限り、シャドウイングとオーバーライドの両方よりも、一意に命名されたプロパティを優先してください。

Virtual、Override、Final キーワード

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