カスタムアクセサ
CoddyのKotlinジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 7/57。
Kotlinのすべてのプロパティにはgetterがあり、すべてのvarにはsetterもあります。デフォルトでは、これらは保存された値を読み書きします。カスタムgetterを使うと、読み取るたびに値を計算します。
class Rectangle(var width: Int, var height: Int) {
val area: Int
get() = width * height
}mainの中で:
val r = Rectangle(3, 4)
println(r.area)
r.width = 10
println(r.area)出力:
12
40カスタムセッターは、プロパティに値が代入されるたびにコードを実行します。その内部では、value が代入された値であり、field はプロパティの背後に保存されている値、つまりバッキングフィールドです。
class Thermostat {
var target = 20
set(value) {
field = value.coerceIn(10, 30)
}
}main の内部では:
val t = Thermostat()
t.target = 42
println(t.target)
t.target = 18
println(t.target)出力:
30
18アクセサー内では、プロパティ名ではなく field を使用します。target のセッター内で target = value と記述すると、セッターが再び呼び出され、永遠に繰り返されます。
var target = 20
set(value) {
// target = value // このセッターを再度呼び出します: 無限再帰
field = value // 値を格納します
}セッターは、変更に反応する場所でもあります。たとえば、変更を数えたり記録したりできます。
class Player(name: String) {
var changes = 0
private set
var name = name
set(value) {
field = value.trim()
changes++
}
}mainの中で:
val p = Player("ada")
p.name = " Ada "
p.name = "Ada L."
println("${p.name} after ${p.changes} changes")出力:
Ada L. after 2 changesチャレンジ
簡単クラス Circle(radius: Double)を完成させてください。radiusはvarであり、セッターは負の値を0として保存します。カスタムゲッターを持つ読み取り専用プロパティdiameterとarea(Math.PIを使ったπ r²)、および面積を小数点以下2桁に丸めたr=2.0 d=4.0 a=12.57を返すlabelを追加してください("%.2f".format(area))。
提供されたコードは1行につき1つの半径を読み取り、labelを出力した後、最後の円の半径を2倍にして、再びlabelを出力します。そのため、値は半径に従って変化しなければなりません。
コードはCircle.ktに記述してください。Main.ktには提供された入出力コードが含まれており、編集できません。
自分で試してみよう
fun main() {
// 提供された入出力コード: そのままにしておく
val input = generateSequence(::readLine).toList()
var last = Circle(0.0)
for (line in input) {
last = Circle(line.toDouble())
println(last.label)
}
last.radius *= 2
println(last.label)
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Kotlinプレイグラウンド