【发布时间】:2015-11-23 15:49:06
【问题描述】:
看起来虽然 QML 支持“覆盖”属性和函数,但这种支持有点笨拙。这是一个示例 sn-p:
// 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])
}
}
覆盖的行为是一致的——无论一个成员被覆盖多少次,你总是得到正确的,即使你做了这样的事情:
QtObject {
property T1 p : T2 {}
Component.onCompleted: console.log(p.p + " " + p.f())
}
虽然该属性是用 T1 类型声明的,但它引用了一个 T2 对象,因此输出显示为“blah blah”。
它也适用于“每个实例”:
T2 {
function f() { return 1.5 }
Component.onCompleted: {
console.log(f())
}
}
迭代 T1 的输出与预期一致:
qml: objectName string
qml: p number 1
qml: objectNameChanged function function() { [code] }
qml: pChanged function function() { [code] }
qml: f function function() { [code] }
但是,T2 的输出有点奇怪:
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] }
它列出了两次“覆盖”成员,但是,似乎不是一个来自“基”类型,另一个来自“派生”——因为两个 p 都是字符串。
var obj = this
for (var k in obj) if ((k === "f") && (typeof obj[k] === "function")) console.log(obj[k]())
同时调用 f 函数两次输出“blah” - 因此同样适用于“覆盖”函数。
我预计迭代“派生”对象会显示属性和函数两次,但其中之一将来自基本类型。让它们实际上是重复的,两者都指代同一个成员似乎毫无意义且不合逻辑。在实例级别覆盖放置另一个成员,并且再次,所有三个都引用最新的覆盖。因此,从技术上讲,甚至无法手动选择覆盖。
所以我的问题是是否可以指定覆盖:
// in T2.qml - pseudocode
property string p: T1::p + "blah" // value is "1 blah"
f() { return T1:: f() + "blah" } // returning "1 blah"
尝试以幼稚的方式去做会导致史诗般的失败:
// 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
【问题讨论】:
标签: javascript function properties overriding qml