Sombreado de propiedades y semántica de sustitución
Sombreado de propiedades
Por defecto, las propiedades pueden ocultarse: Se vuelve a declarar una propiedad en un tipo QML derivado, posiblemente con un nuevo tipo y nuevos atributos. El resultado serán dos propiedades con el mismo nombre, sólo una de las cuales será accesible en un contexto dado. Esto rara vez es lo que se desea. A menudo es accidental, y la mayoría de las veces los efectos son bastante confusos.
Consideremos el siguiente ejemplo, digamos que tenemos un tipo Edificio utilizado en algún software de visualización arquitectónica escrito en QML:
// Building.qml import QtQuick Item { property int floors property string rotation // like CSS rotate, "-120deg" property date constructionDate }
Edificio es un Item ya que hereda de él pero, lo que es importante, la rotation property de Item ha sido ensombrecida por la recién introducida propiedad de rotación en Edificio. Al pasar este objeto a una función genérica que maneje elementos, la función intentará leer la propiedad de rotación del objeto y esperará obtener la propiedad de tipo real definida por Item. En lugar de ello, obtendrá una cadena, lo que conducirá a resultados inesperados.
Esto también es un obstáculo para las herramientas QML. Rara vez puede determinar con certeza el tipo de una propiedad sin ejecutar el código que la manipula. Esto se debe a que el objeto que contiene la propiedad a menudo puede ser de un tipo derivado.
Por lo tanto, esto no sólo confunde al usuario y da lugar a errores inesperados difíciles de detectar, sino que también impide que las herramientas generen código más optimizado.
Para solucionar este problema, se introdujeron las palabras clave final, override y virtual, junto con advertencias y errores adicionales. Su propósito es ayudar a los usuarios a evitar el shadowing accidental y proporcionar mecanismos explícitos para los raros casos en los que una propiedad realmente necesita reemplazar a una propiedad de un tipo base. Denominamos anulación a este tipo de anulación explícita.
Nota: Como se ha explicado anteriormente, el shadowing es a menudo accidental y normalmente conduce a un comportamiento ambiguo y difícil de diagnosticar. Siempre que sea posible, preferimos propiedades con nombre único en lugar de shadowing y overriding.
Palabras clave Virtual, Override, Final
- La palabra clave
finalmarca esta declaración como final. Puede sobrescribir una propiedad de un tipo base, pero no puede ser sobrescrita o sombreada por tipos derivados. Esto ayuda a evitar sombras accidentales y permite a las herramientas QML generar código más optimizado. - La palabra clave
overrideindica que la propiedad anula intencionadamente una propiedad virtual de un tipo base. Una propiedad que sustituye a otra no necesita marcarse comovirtual. Hereda automáticamente la virtualidad de la propiedad que reemplaza. Si la propiedad original es virtual, la sobreescritura también lo es. Si no lo es, la anulación no es válida y ya producirá un error. - La palabra clave
virtualindica explícitamente que la propiedad está destinada a ser anulada. Añadirvirtualen la propiedad que se desea anular no tiene ningún efecto, véaseoverride.
Así es como pueden utilizarse en la práctica:
// 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 }
Nota: es preferible utilizar final en lugar de override
Aquí hay también una extensa lista de combinaciones de `virtual`, `override`, y `final` como referencia:
// 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 }
Nota: La mayoría de las advertencias se convertirán en errores en el futuro, no podemos convertirlas en errores por ahora debido a la compatibilidad con versiones anteriores.
Nota: Esta semántica es aplicada por 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.