Ders 06 / 17
Değişmezlik ve Kararlılık
Platform bir değerin değişip değişmediğini bilirse yeniden oluşturmada atlama yapabilir. Ders yerinde değiştirilen listeyle yeni liste üreten olayın aynı yöne, yukarı gittiğini ama yalnız birinin gözlendiğini ölçer.
Yayın Güncelleme
Bu derste
- Kararlı ve kararsız bir türün farkını platformun bilme ölçütüyle açıklar
- Yerinde değiştirilen listenin ve yeni liste üreten olayın yönünü ölçer
- Gözlenen değişikliğin referansın değişmesine bağlı olduğunu modelde gösterir
- Olayla yeni liste üretmenin yukarı ve aşağı iki hareketten oluştuğunu gösterir
İçindekiler
Önceki ders, girdisi değişmeyen bileşen işlevinin atlandığını varsaymıştı. Bu ders o varsayımı açar: platform bir değerin değişip değişmediğini nasıl bilir? Cevap hareketin yönünü değiştirmez ama hareketin görülüp görülmediğini değiştirir. Dersin sorusu yine aynıdır: bu veri arayüz ağacında hangi yöne gidiyor? İki ayrı biçimde yukarı gidebilir ve yalnız birinde platform bunu fark eder.
// Direction.kt — bir verinin arayuz agacinda hangi yone gittigini siniflandirir
class Tree(private val parentOf: Map<String, String>) {
fun contains(node: String): Boolean = node in parentOf.keys || node in parentOf.values
fun parent(node: String): String? = parentOf[node]
fun ancestors(node: String): List<String> {
val chain = mutableListOf<String>()
var current = parentOf[node]
while (current != null) {
chain.add(current)
current = parentOf[current]
}
return chain
}
}
class Move(val label: String, val from: String, val to: String, tree: Tree) {
val direction: String = when {
!tree.contains(from) || !tree.contains(to) -> "dis"
to in tree.ancestors(from) -> "yukari"
tree.parent(to) == from -> "asagi"
from in tree.ancestors(to) -> "derin"
else -> error("akrabasiz: $from ve $to")
}
fun describe() {
println("$label: kimden=$from | kime=$to -> $direction")
}
}
fun countDirections(moves: List<Move>) {
for (name in listOf("asagi", "yukari", "derin", "dis")) {
println("$name: ${moves.count { it.direction == name }}")
}
}
Platform Neyi Bilir
Platform belgesine göre bir tür, değişmezse ya da değerinin yeniden oluşturmalar arasında değişip değişmediği platform tarafından bilinebiliyorsa kararlıdır. Platformun değeri bilemediği tür kararsızdır. Belgenin örneği: özellikleri val olan bir veri sınıfı değişmezdir; özellikleri var olan sürümde özellikleri değişse platform bunu fark etmezdi, çünkü platform yalnız kendi durum nesnelerindeki değişiklikleri izler.
Liste arayüzleri için belge şunu der: standart koleksiyon arayüzleri (List, Set, Map) kararsız sayılır, çünkü altındaki gerçekleme değiştirilebilir olabilir. Güçlü atlama kipi, belgeye göre Kotlin 2.0.20 ve üzerinde varsayılan olarak açıktır. Kip açıkken kararsız parametreler referans eşitliğiyle (===) karşılaştırılır ve aynı nesne geçilirse bileşen işlevi atlanır.
// Platform kodu: MutableList ve data class
import androidx.compose.runtime.*
class CartState(val items: MutableList<String>)
@Composable
fun CartRow(state: CartState) {
Button(onClick = { state.items.add("c") }) {
Text("Ekle: ${state.items.size}")
}
}
data class CartItems(val items: List<String>)
@Composable
fun CartList(cart: CartItems, onAdd: (CartItems) -> Unit) {
Button(onClick = { onAdd(cart.copy(items = cart.items + "c")) }) {
Text("Ekle: ${cart.items.size}")
}
}
İlk bileşen işlevi listeyi olduğu yerde değiştirir: state ve onun listesi aynı nesne kalır. İkincisi yeni bir CartItems üretir ve değişikliği sahibine olay olarak verir. Bu parça platform kodudur ve burada çıktı iddia etmiyoruz. Model, platformun bu kuralını kurar; model platformun kendisi değildir.
Model “gözlenen”i basit bir kuralla kurar: değişiklikten önceki ve sonraki liste aynı nesneyse platform fark edemez; farklı nesneyse eder. Bir Edit, değişikliği yapanı, listenin sahibini ve önceki ile sonraki listeyi taşır.
// Edits.kt — bir degisikligin yonu ve gozlenip gozlenmedigi
class Edit(
val label: String,
val by: String,
val owner: String,
before: List<String>,
val after: List<String>,
tree: Tree,
) {
val move = Move(label, by, owner, tree)
val observed: Boolean = before !== after
fun report() {
move.describe()
println(" gozlenen=$observed | icerik=$after")
}
}
BI11. Model gözlenmeyi referans farkıyla kurar. Platformun kararlılığı hangi türlerde nasıl çıkardığı, derleyici ayarının etkisi ve eşitlik karşılaştırmasının maliyeti ölçülmedi.
Yerinde Değiştirmek
Çocuk, sahibin listesini olduğu yerde değiştirir. Veri çocuktan sahibe gider; sahip Screen, değiştiren CartRow.
// Main.kt — yerinde degistirme: yon yukari, gozlenen degil
fun main() {
val tree = Tree(mapOf(
"Screen" to "App",
"CartRow" to "Screen",
))
val list = mutableListOf("a", "b")
val before: List<String> = list
list.add("c")
val edit = Edit("degistir", "CartRow", "Screen", before, list, tree)
edit.report()
}
degistir: kimden=CartRow | kime=Screen -> yukari gozlenen=false | icerik=[a, b, c]
Hareketin yönü yukarıdır, çünkü hedef kaynağın atasıdır. Ama liste aynı nesne kaldığı için gozlenen=false: içerik değişti, platform değişikliği öğrenmedi. Ekran eski içerikle kalabilir.
Olayla Yeni Liste
Çocuk listeyi değiştirmez; sahibine olay verir, sahip yeni liste üretir.
// Main.kt — olayla yeni liste: yon yukari, gozlenen
fun main() {
val tree = Tree(mapOf(
"Screen" to "App",
"CartRow" to "Screen",
))
val before = listOf("a", "b")
val after = before + "c"
val edit = Edit("olay", "CartRow", "Screen", before, after, tree)
edit.report()
}
olay: kimden=CartRow | kime=Screen -> yukari gozlenen=true | icerik=[a, b, c]
Yön aynıdır: yukarı. Liste yeni nesne olduğu için gozlenen=true. Dersin yönü budur: yukarı.
Olayın hikâyesi burada bitmez. Sahip yeni listeyi bildiğinde onu aşağı, okuyucuya verir.
// Main.kt — tam akis: bir yukari, bir asagi
fun main() {
val tree = Tree(mapOf(
"Screen" to "App",
"CartRow" to "Screen",
))
val moves = listOf(
Move("olay", "CartRow", "Screen", tree),
Move("yeni-liste", "Screen", "CartRow", tree),
)
moves.forEach { it.describe() }
countDirections(moves)
}
olay: kimden=CartRow | kime=Screen -> yukari yeni-liste: kimden=Screen | kime=CartRow -> asagi asagi: 1 yukari: 1 derin: 0 dis: 0
Yerinde değiştirmede yalnız bir hareket vardır ve geri dönüş yoktur. Olayla yeni liste ise iki hareketten oluşur: olay yukarı, yeni liste aşağı. Ders 03’teki akışın aynısıdır. Yukarıdaki iki satır kuralı göstermek için yazılmıştır, ölçüm değildir: ikisinde de uçlar elle yazılmıştır.
Bu ders M31/K01’den farklıdır. O kurs iki değerin eşit sayılıp sayılmayacağını kurdu. Burada eşitlik ölçülmez; ölçülen, hareketin yönü ve değişikliğin görülüp görülmediğidir.
BI12. Sahibin yeni listeyi aşağı vermesi modelde bir hareket olarak kurulur. Platformda yeni listenin hangi kapsamlarda yeniden oluşturmaya yol açtığı ölçülmedi.
Sınırlayıcı Ölçüm
Aynı değiştiren, aynı sahip, aynı içerik. İki değişiklik yöntemi yan yana.
// Main.kt — ayni yon, farkli gozlenme
fun main() {
val tree = Tree(mapOf(
"Screen" to "App",
"CartRow" to "Screen",
))
val inPlace = mutableListOf("a", "b")
val beforeInPlace: List<String> = inPlace
inPlace.add("c")
val copied = listOf("a", "b")
val a = Edit("yerinde", "CartRow", "Screen", beforeInPlace, inPlace, tree)
val b = Edit("kopya", "CartRow", "Screen", copied, copied + "c", tree)
println("yerinde: yon=${a.move.direction} gozlenen=${a.observed}")
println("kopya: yon=${b.move.direction} gozlenen=${b.observed}")
}
yerinde: yon=yukari gozlenen=false kopya: yon=yukari gozlenen=true
İki değişiklik aynı yöne gider. Fark yönde değil, gözlenmededir. Kural yöne baktığı için ikisine aynı cevabı verir; görülüp görülmediği ise listenin nesne olarak değişmesine bağlıdır.
Özet
- Bu dersin yönü: yukarı. Çocuğun sahibin listesini değiştirmesi de, sahibe olay vermesi de yukarı gider.
- Yerinde değiştirmede içerik değişti ama gözlenen değil: yukarı 1, gözlenen false.
- Olayla yeni liste üretmede aynı yön gözlenen true ile ölçüldü.
- Olayla yeni liste iki hareketle gösterilir: olay yukarı, yeni liste aşağı. Bu gösterim bir ölçüm değildir; uçları elle yazılmıştır.
- Aynı yönün iki yöntemi yan yana ölçüldü: ikisi de yukarı, yalnız kopya gözlenen.
Sonraki Adım
Bu ders bileşen işlevi modelini kapatır: bileşen işlevi, durum, durumu kaldırma, yeniden oluşturma, yan etkiler ve kararlılık. Sıradaki konu, Temel Düzenler, bu modelin üstüne ekrandaki düzeni kurar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.