解析属性和函数“覆盖"在 QML 中 [英] Resolving property and function "overrides" in QML

查看:27
本文介绍了解析属性和函数“覆盖"在 QML 中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看起来虽然 QML 支持覆盖"属性和函数,但这种支持有点笨拙.这是一个示例片段:

//T1.qmlQtObject {属性 int p: 1函数 f() { 返回 1 }}//T2.qmlT1{属性字符串 p:等等"函数 f() { 返回等等"}}//用法T1{Component.onCompleted:{var obj = 这个for (var k in obj) console.log(k + " " + typeof obj[k] + " " + obj[k])}}T2{Component.onCompleted:{var obj = 这个for (var k in obj) console.log(k + " " + typeof obj[k] + " " + obj[k])}}

覆盖的行为是一致的——无论一个成员被覆盖多少次,你总是得到正确的,即使你做这样的事情:

QtObject {属性 T1 p : T2 {}Component.onCompleted: console.log(p.p + " " + p.f())}

虽然该属性是用类型 T1 声明的,但它引用了一个 T2 对象,因此输出显示blah blah".

它也适用于每个实例":

T2 {函数 f() { 返回 1.5 }Component.onCompleted:{控制台日志(f())}}

迭代 T1 的输出符合预期:

qml: objectName 字符串qml: p 数 1qml:objectNameChanged 函数 function() { [code] }qml: pChanged 函数 function() { [code] }qml: f 函数 function() { [代码] }

然而,T2 的输出有点奇怪:

qml: objectName 字符串qml:p 字符串等等qml:p 字符串等等qml:objectNameChanged 函数 function() { [code] }qml: pChanged 函数 function() { [code] }qml: f 函数 function() { [代码] }qml: pChanged 函数 function() { [code] }qml: f 函数 function() { [代码] }

它列出了两次覆盖"成员,但是,似乎一个来自基本"类型,另一个来自派生" - 因为两个 p 都是字符串.

var obj = thisfor (var k in obj) if ((k === "f") && (typeof obj[k] === "function")) console.log(obj[k]())

调用两个 f 函数会输出blah"两次 - 所以同样适用于overrides"函数.

我预计迭代派生"对象会显示属性和函数两次,但其中之一将来自基类型.让它们实际上重复,两者都指的是同一个成员似乎毫无意义和不合逻辑.在实例级别进行覆盖会放置另一个成员,并且所有三个成员再次引用最新的覆盖.因此,在技术上甚至无法手动选择覆盖.

所以我的问题是是否可以指定覆盖:

//在 T2.qml 中 - 伪代码属性字符串 p: T1::p + "blah"//值为 "1 blah"f() { return T1:: f() + "blah" }//返回 "1 blah"

尝试以幼稚的方式去做会导致史诗般的失败:

//在T2.qml中property string p: p + "blah"//绑定循环,p 不是指 T1 的 pf() { return f() + "blah" }//堆栈溢出,f 不是指 T1 的 f

解决方案

找到了一个简单天真的手动解决方案:

//T1.qmlQtObject {函数 f() { 返回 f_t1() }函数 f_t1() { 返回 1 }}//T2.qmlT1{函数 f() { 返回 f_t2() }函数 f_t2() { 返回 f_t1() + "等等" }}//用法T2{函数 f() { 返回 f_t2() + 1.5}Component.onCompleted: console.log(f())//输出 1 blah 1.5}

简而言之,为覆盖的继承"的每个级别显式命名函数,并使用未修饰的函数覆盖进行多态访问,因此现在基"类型实现可以被派生重用.

It seems like although QML supports "overriding" of properties and functions, the support is somewhat clunky. Here is an example snippet:

// T1.qml
QtObject {
    property int p: 1
    function f() { return 1 }
}

// T2.qml
T1 {
    property string p: "blah"
    function f() { return "blah" }
}


// usage
T1 {
    Component.onCompleted: {
        var obj = this
        for (var k in obj) console.log(k + " " + typeof obj[k] + " " + obj[k])
    }
}

T2 {
    Component.onCompleted: {
        var obj = this
        for (var k in obj) console.log(k + " " + typeof obj[k] + " " + obj[k])
    }
}

The behavior of overrides is consistent - no matter how many times a member was overridden, you always get the right one, even if you do something like this:

QtObject {
    property T1 p : T2 {}
    Component.onCompleted: console.log(p.p + " " + p.f())
}

Although the property is declared with type T1, it references a T2 object, and thus the output says "blah blah".

It also works on a `per instance" basis:

T2 {
    function f() { return 1.5 }
    Component.onCompleted: {
       console.log(f())
    }
}

The output from iterating T1 is as expected:

qml: objectName string 
qml: p number 1
qml: objectNameChanged function function() { [code] }
qml: pChanged function function() { [code] }
qml: f function function() { [code] }

However, the output for T2 is a little odd:

qml: objectName string 
qml: p string blah
qml: p string blah
qml: objectNameChanged function function() { [code] }
qml: pChanged function function() { [code] }
qml: f function function() { [code] }
qml: pChanged function function() { [code] }
qml: f function function() { [code] }

It lists the "overridden" members twice, however, it doesn't seem like one is from the "base" type and the other from the "derived" - as both p's are strings.

var obj = this
for (var k in obj) if ((k === "f") && (typeof obj[k] === "function")) console.log(obj[k]())

Calling both f functions outputs "blah" twice - so the same applies for the function "overrides" as well.

I expected that iterating the "derived" object would show the property and function twice, but one of those would be from the base type. Having them practically duplicated, both referring to the same member seems pointless and illogical. Overriding at instance level puts yet another member, and once again, all three reference the latest override. So it is technically not possible to even pick the overrides manually.

So my question is whether it is possible to specify the overrides:

// in T2.qml - pseudocode
property string p: T1::p + "blah" //  value is "1 blah"
f() { return T1:: f() + "blah" } //  returning "1 blah"

Attempting to do it in the naive way results in an epic fail:

// in T2.qml
property string p: p + "blah" //  binding loop, p does not refer to T1's p
f() { return f() + "blah" } //  stack overflow, f does not refer to T1's f

解决方案

Found one simple and naive manual solution:

// T1.qml
QtObject {
    function f() { return f_t1() }
    function f_t1() { return 1 }
}

// T2.qml
T1 {
    function f() { return f_t2() }
    function f_t2() { return f_t1() + " blah " }
}

// usage
T2 {
    function f() { return f_t2() + 1.5}
    Component.onCompleted: console.log(f()) // outputs 1 blah 1.5
}

In short, have explicitly named function for every level of the "inheritance" that overrides, and use the non-decorated function override for polymorphic access, thus now the "base" type implementations can be reused by the derived.

这篇关于解析属性和函数“覆盖"在 QML 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆