プロパティのシャドウイングとオーバーライドのセマンティクス
プロパティのシャドウイング
デフォルトでは、プロパティはシャドウイングされる可能性があります。つまり、派生した QML 型内でプロパティを再宣言することができ、その際、新しい型や新しい属性を指定することも可能です。その結果、同じ名前のプロパティが 2 つ存在することになりますが、特定のコンテキストではそのうちの 1 つにしかアクセスできません。これは、望ましい結果となることはめったにありません。 多くの場合、これは意図しないものであり、その影響はしばしば非常に混乱を招くものです。
次の例を考えてみましょう。QMLで記述された建築可視化ソフトウェアで使用される「Building」という型があるとします:
// Building.qml
import QtQuick
Item {
property int floors
property string rotation // like CSS rotate, "-120deg"
property date constructionDate
}`Building`は`Item`を継承しているため`Item`の一種ですが、重要な点として、`Item `の`rotation property `が、`Building`に新たに導入された`rotation`プロパティによってシャドーされています。 このオブジェクトを`Item`を扱う汎用関数に渡すと、その関数はオブジェクトの`rotation`プロパティを読み取ろうとし、Item で定義された`real`型のプロパティが返ってくることを期待します。しかし、実際には文字列が返され、予期しない結果につながります。
これは QML ツール群にとっても障害となります。プロパティを操作するコードを実行せずに、その型を確実に特定できることはめったにありません。これは、プロパティを保持するオブジェクトが派生型である場合が多いためです。
したがって、これはユーザーを混乱させ、発見が困難な予期せぬバグを招くだけでなく、ツールがより最適化されたコードを生成することを妨げることにもなります。
この問題に対処するため、final 、override 、virtual というキーワードが、追加の警告やエラーとともに導入されました。これらは、ユーザーが意図しないシャドウイングを回避できるよう支援するとともに、プロパティが基底型のプロパティを真に置き換える必要がある稀なケースに対して、明示的なメカニズムを提供することを目的としています。このような明示的なシャドウイングを「オーバーライド」と呼びます。
注:前述の通り 、シャドウイングは多くの場合意図せず発生し、通常は曖昧で診断が困難な挙動を招きます。可能な限り、シャドウイングやオーバーライドを行うよりも、一意な名前を持つプロパティを使用することを推奨します。
Virtual、Override、Final キーワード
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.