QML:在派生类中将属性设置为只读

5

我相信答案是否定的,但我还是想问一下。在一个纯QML派生类中,可以将继承的属性设置为只读/常量吗?

// Base.qml
Item {
    property int foo: 42
}

// Derived.qml
Base {
    foo: 99 // Make constant somehow!
}

我目前的方法是检测foo是否发生变化并在控制台打印错误信息,但这不是良好API的标志...
我有一个菜单项类,它可以表示菜单条目、子菜单、分隔符等。我需要特定的行为,但仅在它处于子菜单模式下。我可以更改继承树,以便每个菜单类型都有一个子类,但这似乎很愚蠢,因为每个子类将只包含单个readonly属性。然而,如果没有其他方法,那我就必须这样做。

你想在这里得到什么?你需要它做什么?也许还有其他解决方案。 - folibis
@folibis,我已经更新了我的问题。 - cmannett85
2个回答

5

您还可以将 foo 作为一个 readonly alias 转换为内部属性 _foo,仅在派生类中用于赋值:

// Base.qml
Item {
    id: base

    readonly property alias foo: base._foo

    property int _foo: 42 // only used for assignment in subclasses
}

用于另一个组件:

Item {
    Base {
        id: child0
    }

    Base {
        id: child1
        _foo: 99
    }

    Base {
        id: child2
        _foo: child1.foo
    }

    Component.onCompleted: {
        console.log("child0:", child0.foo,"child1:", child1.foo, "child2:", child2.foo)
        child1.foo = 5 // not allowed!
        console.log("child0:", child0.foo,"child1:", child1.foo, "child2:", child2.foo)
    }
}

输出:

child0: 42 child1: 99 child2: 99
TypeError: Cannot assign to read-only property "foo"

注意:当然仍然可以稍后修改_foo。但是,如果您记得仅将其用于赋值,则在派生类中具有只读的foo所需的行为。

4
为什么不使用继承的getter/setters来处理私有foo?类似于:
//Base.qml
Item
{
    QtObject
    {
       id : privateFoo
       property int foo : 42
    }

    function getFoo() {return privateFoo.foo;}
    function setFoo(newFoo) { privateFoo.foo = newFoo; }
}

//derived.qml
Base
{
    function getFoo() {return 99;}
    function setFoo(newFoo) { /*do nothing */ }
}

(我还没有测试过这段代码)


这很好,我唯一的担忧是它不能通过“QML范例”即属性操作来解决问题。话虽如此,属性绑定仍然按预期工作,所以我也无法过多抱怨。 - cmannett85
是的,这很遗憾,私有属性的约定是在它们的名称前加上 __,例如这里的 __foo,但这并不能阻止任何人修改此属性。这只是一个指示,表明该属性仅供内部使用。 - GrecKo
六年过去了:应该从正确答案中去掉勾选,因为它是错误的。使用“readonly property alias foo: base._foo”。 - basjak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接