Masquage des propriétés et sémantique de la redéfinition
Masquage des propriétés
Par défaut, les propriétés peuvent être masquées: vous redéclarez une propriété dans un type QML dérivé, éventuellement avec un nouveau type et de nouveaux attributs. Il en résulte deux propriétés portant le même nom, dont une seule est accessible dans un contexte donné. C'est rarement ce que vous souhaitez. C'est souvent accidentel, et la plupart du temps, les effets sont assez déroutants.
Prenons l’exemple suivant : supposons que nous ayons un type `Building` utilisé dans un logiciel de visualisation architecturale écrit en QML :
// Building.qml
import QtQuick
Item {
property int floors
property string rotation // like CSS rotate, "-120deg"
property date constructionDate
}`Building` est un `Item` puisqu’il en hérite, mais, et c’est important, l’ rotation property e ` Item ` a été masquée par la nouvelle propriété `rotation` introduite sur `Building`. Lorsque cet objet est transmis à une fonction générique gérant les « Items », la fonction tente de lire la propriété « rotation » de l’objet et s’attend à obtenir en retour la propriété de type « real » définie par Item. Au lieu de cela, elle obtient une chaîne de caractères, ce qui conduit à des résultats inattendus.
Cela constitue également un obstacle pour les outils QML. Ceux-ci peuvent rarement déterminer le type d’une propriété avec certitude sans exécuter le code qui la manipule. En effet, l’objet contenant la propriété peut souvent être d’un type dérivé.
Par conséquent, cela non seulement sème la confusion chez l’utilisateur et entraîne des bogues inattendus difficiles à détecter, mais empêche également les outils de générer un code plus optimisé.
Pour remédier à cela, les mots-clés ` final`, ` override` et ` virtual ` — ainsi que des avertissements et des erreurs supplémentaires — ont été introduits. Leur objectif est d’aider les utilisateurs à éviter les masquages accidentels et de fournir des mécanismes explicites pour les rares cas où une propriété doit véritablement remplacer une propriété d’un type de base. Nous appelons « redéfinition » ce type de masquage explicite.
Remarque : comme expliqué ci-dessus, le masquage est souvent accidentel et entraîne généralement un comportement ambigu et difficile à diagnostiquer. Privilégiez, dans la mesure du possible, l’utilisation de propriétés portant un nom unique plutôt que le masquage ou la redéfinition.
Mots-clés `virtual`, `override` et `final`
- Le mot-clé «
final» marque cette déclaration comme « final ». Elle peut redéfinir une propriété d’un type de base, mais ne peut être ni redéfinie ni masquée par des types dérivés. Cela permet d’éviter le masquage accidentel et permet aux outils QML de générer un code plus optimisé. - Le mot-clé «
override» indique que la propriété remplace intentionnellement une propriété virtuelle d’un type de base. Une propriété qui en remplace une autre n’a pas besoin d’être marquée comme «virtual». Elle hérite automatiquement du caractère virtuel de la propriété qu’elle remplace. Si la propriété d’origine est virtuelle, la propriété de remplacement l’est également. Dans le cas contraire, la propriété de remplacement n’est pas valide et génère une erreur. - Le mot-clé «
virtual» indique explicitement que la propriété est destinée à être redéfinie. L’ajout de «virtual» à la propriété redéfinissante n’a aucun effet, voiroverride.
Voici comment les utiliser en pratique :
// 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
}Remarque : privilégiez l’utilisation de ` final ` plutôt que override
Voici également une liste exhaustive des combinaisons de `virtual`, `override` et `final` à titre de référence :
// 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
}Remarque : la plupart de ces avertissements deviendront des erreurs à l'avenir, mais nous ne pouvons pas les transformer en erreurs pour l'instant pour des raisons de rétrocompatibilité.
Remarque : ces règles sémantiques sont appliquées par le 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.