Eigenschaftsschattierung und Überschreibungssemantik
Schattierung von Eigenschaften
Standardmäßig können Eigenschaften beschattet werden: Sie deklarieren eine Eigenschaft in einem abgeleiteten QML-Typ neu, möglicherweise mit einem neuen Typ und neuen Attributen. Das Ergebnis sind zwei Eigenschaften mit demselben Namen, von denen nur eine in einem bestimmten Kontext zugänglich ist. Das ist selten das, was Sie wollen. Oft ist es unbeabsichtigt, und meistens sind die Auswirkungen ziemlich verwirrend.
Betrachten wir das folgende Beispiel: Nehmen wir an, wir haben einen Typ Building, der in einer in QML geschriebenen Software zur Architekturvisualisierung verwendet wird:
// Building.qml import QtQuick Item { property int floors property string rotation // like CSS rotate, "-120deg" property date constructionDate }
Building ist ein Item, da es von diesem erbt, aber, was wichtig ist, die rotation property von Item wurde durch die neu eingeführte Rotationseigenschaft von Building verdrängt. Wenn dieses Objekt an eine generische Funktion übergeben wird, die Items behandelt, wird die Funktion versuchen, die Rotationseigenschaft des Objekts zu lesen und erwarten, dass sie die von Item definierte Eigenschaft vom Typ real zurückbekommt. Stattdessen erhält sie einen String zurück, was zu unerwarteten Ergebnissen führt.
Dies ist auch ein Hindernis für das QML-Tooling. Es kann den Typ einer Eigenschaft selten mit Sicherheit bestimmen, ohne den Code auszuführen, der die Eigenschaft manipuliert. Der Grund dafür ist, dass das Objekt, das die Eigenschaft enthält, oft von einem abgeleiteten Typ sein kann.
Dies verwirrt nicht nur den Benutzer und führt zu unerwarteten, schwer zu entdeckenden Fehlern, sondern hindert auch das Tooling daran, optimierten Code zu erzeugen.
Um dies zu beheben, wurden die Schlüsselwörter final, override und virtual - zusammen mit zusätzlichen Warnungen und Fehlern - eingeführt. Ihr Zweck ist es, den Benutzern zu helfen, versehentliches Shadowing zu vermeiden und explizite Mechanismen für die seltenen Fälle bereitzustellen, in denen eine Eigenschaft wirklich eine Eigenschaft eines Basistyps ersetzen muss. Wir bezeichnen ein solches explizites Shadowing als Overriding.
Hinweis: Wie oben erklärt, ist Shadowing oft unbeabsichtigt und führt in der Regel zu mehrdeutigem und schwer zu diagnostizierendem Verhalten. Bevorzugen Sie eindeutig benannte Eigenschaften gegenüber sowohl Shadowing als auch Overriding, wann immer dies möglich ist.
Schlüsselwörter Virtual, Override, Final
- Das Schlüsselwort
finalkennzeichnet diese Deklaration als endgültig. Sie kann eine Eigenschaft eines Basistyps außer Kraft setzen, aber sie kann nicht von abgeleiteten Typen außer Kraft gesetzt oder überschattet werden. Dies hilft, versehentliches Shadowing zu verhindern und ermöglicht es den QML-Werkzeugen, optimierten Code zu generieren. - Das Schlüsselwort
overridezeigt an, dass die Eigenschaft absichtlich eine virtuelle Eigenschaft eines Basistyps außer Kraft setzt. Eine Eigenschaft, die eine andere außer Kraft setzt, muss nicht alsvirtualgekennzeichnet werden. Sie erbt automatisch die Virtualität der Eigenschaft, die sie außer Kraft setzt. Wenn die ursprüngliche Eigenschaft virtuell ist, ist auch die überschriebene Eigenschaft virtuell. Ist dies nicht der Fall, ist die Überschreibung ungültig und führt bereits zu einem Fehler. - Das Schlüsselwort
virtualzeigt ausdrücklich an, dass die Eigenschaft überschrieben werden soll. Das Hinzufügen vonvirtualzur überschreibenden Eigenschaft hat keine Wirkung, sieheoverride.
So können sie in der Praxis verwendet werden:
// 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 }
Hinweis: Verwenden Sie lieber final als override
Hier ist auch eine umfangreiche Liste von Kombinationen von `virtual`, `override`, und `final` als Referenz:
// 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 }
Hinweis: Die meisten Warnungen werden in der Zukunft zu Fehlern werden, wir können sie wegen der Abwärtskompatibilität vorerst nicht in Fehler umwandeln.
Anmerkung: Diese Semantik wird von der QmlEngine erzwungen.
© 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.