Można zdefiniować tylko właściwość rozszerzenia z niestandardowym programem pobierającym (i programem ustawiającym dla var
) lub delegated property.
pole pomocnicze, przydają się właściwości delegowane. Ideą jest stworzenie delegata właściwość, że przechowywania mapowanie
obiekt do wartości:
użyciu tożsamości, nie equals()
/hashCode()
, aby rzeczywiście przechowywania wartości dla każdego obiektu, jak IdentityHashMap
robi;
nie zapobiegając kluczowych obiektów z czym zbierane śmieci (stosując weak references), jak WeakHashMap
nie.
Niestety, nie ma WeakIdentityHashMap
w JDK, więc trzeba zaimplementować własną (lub wziąć complete implementation).
Następnie, w oparciu o to odwzorowanie, można utworzyć klasę uczestników spełniającą wymagania property delegates requirements. Oto przykład nie bezpieczny wątku wykonania:
class FieldProperty<R, T : Any>(
val initializer: (R) -> T = { throw IllegalStateException("Not initialized.") }
) {
private val map = WeakIdentityHashMap<R, T>()
operator fun getValue(thisRef: R, property: KProperty<*>): T =
map[thisRef] ?: setValue(thisRef, property, initializer(thisRef))
operator fun setValue(thisRef: R, property: KProperty<*>, value: T): T {
map[thisRef] = value
return value
}
}
Przykład zastosowania:
var Int.tag: String by FieldProperty { "$it" }
fun main(args: Array<String>) {
val x = 0
println(x.tag) // 0
val z = 1
println(z.tag) // 1
x.tag = "my tag"
z.tag = x.tag
println(z.tag) // my tag
}
Gdy zdefiniowana wewnątrz klasy odwzorowanie może być przechowywany oddzielnie dla instancje klasy lub też na współdzielony obiekt uczestnika:
private val bATag = FieldProperty<Int, String> { "$it" }
class B() {
var A.someCounter: Int by FieldProperty { 0 } // independent for each instance of B
var A.tag: String by bATag // shared between the instances, but usable only inside B
}
Należy również pamiętać, że tożsamość is not guaranteed dla pri Java typy myszy z powodu boksu.
Podejrzewam, że wydajność tego rozwiązania jest znacznie gorsza niż w przypadku zwykłych pól, prawdopodobnie zbliżonych do normalnych Map
, ale to wymaga dalszych testów.
Aby uzyskać informacje na temat obsługi atrybutów nullable i implementacji wątków, należy zapoznać się z here.
to bardzo fajny twórczy hack. Możesz dodać plik licencji do github. Dzięki! – MadDeveloper