2016-05-18 11 views
6

Ich möchte eine Variable eines bestimmten Typs erstellen, der nicht null ist, sagen Foo zum Beispiel.Lazy Variable mit Reset

Ich möchte dann alle Zugriff auf die Variable Foo zurückgeben, genau wie ein fauler Delegat, aber ich möchte auch in der Lage sein, es zurückzusetzen.

Etwas wie:

var foo : String by Foo(init: {"bar"}) 

print(foo) // prints "bar" 
foo = null // or foo.reset() 
print(foo) // prints "bar" 

Das Problem, das ich zu lösen versuche: Ich habe einen Index für einen Adapter, dass ich die Adapter Inhalt ändert sich, wenn neu erstellen müssen. Also bei Änderung möchte ich den Index löschen, und das nächste Mal, wenn jemand versucht, darauf zuzugreifen, möchte ich es neu erstellen.

+0

Was ist das Ziel oder das Problem, das Sie versuchen zu lösen? – miensol

+0

Fügen Sie das echte Problem der Frage hinzu! – Heinrisch

Antwort

6

Wenn das Ziel ist, ein fauler var property initialisiert zu haben, die zurückgesetzt werden kann, um es Anfangszustand Sie Kotlin die anpassen können SynchronizedLazyImpl die Invalidier Funktion zu ermöglichen:

private object UNINITIALIZED_VALUE 
class InvalidatableLazyImpl<T>(private val initializer:() -> T, lock: Any? = null) : Lazy<T>, Serializable { 
    @Volatile private var _value: Any? = UNINITIALIZED_VALUE 
    private val lock = lock ?: this 
    fun invalidate(){ 
     _value = UNINITIALIZED_VALUE 
    } 

    override val value: T 
     get() { 
      val _v1 = _value 
      if (_v1 !== UNINITIALIZED_VALUE) { 
       return _v1 as T 
      } 

      return synchronized(lock) { 
       val _v2 = _value 
       if (_v2 !== UNINITIALIZED_VALUE) { 
        _v2 as T 
       } 
       else { 
        val typedValue = initializer() 
        _value = typedValue 
        typedValue 
       } 
      } 
     } 


    override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE 

    override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet." 

    operator fun setValue(any: Any, property: KProperty<*>, t: T) { 
     _value = t 
    } 
} 

die dann dazu verwendet werden könnten, wie folgt:

private val fooDelegate = InvalidatableLazyImpl({"bar"}) 
var foo:String by fooDelegate 

println(foo); // -> "bar" 
foo = "updated" 
println(foo); // -> "updated" 
fooDelegate.invalidate() 
println(foo); // -> "bar" 

eine offensichtlich die Delegierten Implementierung ändern könnte, damit für null Wert als Reset es den Code machen könnte jedoch handeln schwieriger zu begründen etwa:

println(obj.foo); //-> prints "bar 
obj.foo = null //reset the value, implicitely 
println(obj.foo); //-> prints "bar", but hey didn't I just said `null` 
+0

Danke für die Antwort! Sie kommen zu dem Problem, dass ich mich gefragt habe, ob es eine Lösung dafür gibt. Ich möchte foo nicht etwas Neues zuweisen, wie foo = "updated", und wie du geschrieben hast, ist obj.foo = null auch nicht bevorzugt. – Heinrisch

+1

Schöne Lösung. Ich bin der Meinung, dass 'foo = null' schwer zu verstehen ist. Als kleinerer Vorschlag an andere Leser würde ich vorschlagen, die 'reset'-Methode in' invalidate' umzubenennen, da Sie das wirklich tun - den zwischengespeicherten Wert ungültig machen. – ean5533

+0

@ ean5533 Sinn machen, Ihren Vorschlag aufgenommen, danke. – miensol