이 페이지에서

속성 가림 및 재정의 의미론

속성 가림

기본적으로 속성은 가릴 수 있습니다. 파생된 QML 유형에서 속성을 재선언할 때, 새로운 유형이나 새로운 속성을 추가할 수 있습니다. 그 결과 동일한 이름을 가진 두 개의 속성이 생기게 되며, 주어진 컨텍스트에서는 그중 하나에만 접근할 수 있습니다. 이는 원하는 경우가 거의 없습니다. 대개는 의도치 않게 발생하며, 대부분의 경우 그 결과는 상당히 혼란스럽습니다.

다음 예제를 살펴보겠습니다. 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.