Auf dieser Seite

Eigenschaftsüberschreibung und Semantik der Überschreibung

Eigenschaftsüberschattung

Standardmäßig können Eigenschaften überschattet werden: Sie deklarieren eine Eigenschaft in einem abgeleiteten QML-Typ erneut, möglicherweise mit einem neuen Typ und neuen Attributen. Das Ergebnis sind zwei Eigenschaften mit demselben Namen, von denen in einem bestimmten Kontext jeweils nur eine zugänglich ist. Dies ist selten beabsichtigt. Oft geschieht dies 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 Architekturvisualisierungssoftware 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 – und das ist entscheidend – die Eigenschaft „ rotation property “ von „ Item “ wurde durch die neu eingeführte Eigenschaft „rotation“ in „Building“ überschrieben. Wird dieses Objekt an eine generische Funktion übergeben, die mit „Items“ arbeitet, versucht die Funktion, die „rotation“-Eigenschaft des Objekts auszulesen, und erwartet, die Eigenschaft vom Typ „real“ zurückzubekommen, die durch Item definiert ist. Stattdessen erhält sie eine Zeichenkette zurück, was zu unerwarteten Ergebnissen führt.

Dies stellt auch ein Hindernis für die QML-Entwicklungswerkzeuge dar. Sie können den Typ einer Eigenschaft selten mit Sicherheit bestimmen, ohne den Code auszuführen, der diese Eigenschaft bearbeitet. Dies liegt daran, dass das Objekt, das die Eigenschaft enthält, oft von einem abgeleiteten Typ sein kann.

Dies verwirrt daher nicht nur den Benutzer und führt zu unerwarteten, schwer zu findenden Fehlern, sondern hindert die Tooling-Umgebung auch daran, optimierteren Code zu generieren.

Um dem entgegenzuwirken, wurden die Schlüsselwörter „ final “, „ override “ und „ virtual “ – zusammen mit zusätzlichen Warnungen und Fehlern – eingeführt. Ihr Zweck ist es, Benutzern dabei zu helfen, versehentliches Shadowing zu vermeiden und explizite Mechanismen für die seltenen Fälle bereitzustellen, in denen eine Eigenschaft tatsächlich eine Eigenschaft eines Basistyps ersetzen muss. Wir bezeichnen ein solches explizites Shadowing als „Overriding“.

Hinweis: Wie oben erläutert, erfolgt das Überschreiben oft unbeabsichtigt und führt in der Regel zu mehrdeutigem und schwer zu diagnostizierendem Verhalten. Bevorzugen Sie nach Möglichkeit eindeutig benannte Eigenschaften gegenüber sowohl dem Überschreiben als auch dem „Overriding“.

Schlüsselwörter „virtual“, „override“ und „final“

  • Das Schlüsselwort „ final “ kennzeichnet diese Deklaration als „final“. Sie kann eine Eigenschaft eines Basistyps überschreiben, kann jedoch selbst nicht von abgeleiteten Typen überschrieben oder überschattet werden. Dies hilft, unbeabsichtigtes Überschatten zu verhindern, und ermöglicht es QML-Tools, optimierteren Code zu generieren.
  • Das Schlüsselwort „ override “ gibt an, dass die Eigenschaft absichtlich eine virtuelle Eigenschaft eines Basistyps überschreibt. Eine Eigenschaft, die eine andere überschreibt, muss nicht als „ virtual “ gekennzeichnet werden. Sie erbt automatisch die Virtualität der Eigenschaft, die sie überschreibt. Ist die ursprüngliche Eigenschaft virtuell, ist auch die Überschreibung virtuell. Ist dies nicht der Fall, ist die Überschreibung ungültig und führt bereits zu einem Fehler.
  • Das Schlüsselwort „ virtual “ gibt ausdrücklich an, dass die Eigenschaft zum Überschreiben vorgesehen ist. Das Hinzufügen von „ virtual “ zur überschreibenden Eigenschaft hat keine Auswirkung, siehe override.

So lassen sie sich in der Praxis verwenden:

// 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 Sievorzugsweise „ final “ anstelle von override

Hier finden Sie außerdem eine umfassende Liste von Kombinationen aus `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 Zukunft zu Fehlern werden; aus Gründen der Abwärtskompatibilität können wir sie derzeit jedoch noch nicht in Fehler umwandeln.

Hinweis: Diese Semantik wird von der QmlEngine durchgesetzt.

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