Разрешение переопределения свойств и функций в QML
Кажется, что хотя QML поддерживает «переопределение» свойств и функций, поддержка несколько неуклюжа. Вот пример фрагмента:
// 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, и, следовательно, вывод говорит «бла-бла».
Это также работает на основе «для каждого экземпляра»:
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
Функция выдает «бла» дважды - то же самое относится и к функции «переопределения».
Я ожидал, что повторение «производного» объекта покажет свойство и функцию дважды, но один из них будет из базового типа. Практически дублировать их, когда оба ссылаются на одного и того же члена, кажется бессмысленным и нелогичным. Переопределение на уровне экземпляра помещает еще одного члена, и снова все три ссылаются на последнее переопределение. Таким образом, технически невозможно даже выбрать переопределения вручную.
Поэтому мой вопрос заключается в том, можно ли указать переопределения:
// 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