オープンクラスとサブクラス
CoddyのKotlinジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 17/57。
継承を使うと、あるクラスを基に別のクラスを作成できます。サブクラスはスーパークラスのすべてのプロパティとメソッドを受け継ぎ、独自のものを追加できます。Kotlinのクラスはデフォルトで継承不可のため、別のクラスが拡張できるようにするには、クラスにopenを指定する必要があります。
open class Animal(val name: String) {
fun describe() = "$name is an animal"
}
class Dog(name: String) : Animal(name) {
fun fetch() = "$name fetches the ball"
}mainの中では:
val rex = Dog("Rex")
println(rex.describe())
println(rex.fetch())出力:
Rex is an animal
Rex fetches the ballclass Dog(name: String) : Animal(name)は、DogがAnimalを継承し、nameをスーパークラスのコンストラクターに渡すことを示しています。Animalにすでにプロパティが存在するため、このパラメーターにはvalがありません。openでないクラスは継承できません。
class Plant(val name: String)
// class Tree(name: String) : Plant(name) // エラー: この型はfinalなので継承できない
open class Vehicle(val wheels: Int)
class Bike : Vehicle(2) // 固定値を渡す
class Truck(val load: Int) : Vehicle(6) // 独自のプロパティを追加するDogはAnimalなので、サブクラスのインスタンスはスーパークラスの型が期待される場所ならどこでも使用できます。1つのList<Animal>には犬、猫、通常の動物を格納でき、各要素はAnimalのメンバーを持ちます。
open class Animal(val name: String) {
fun describe() = "$name is an animal"
}
class Dog(name: String) : Animal(name)
class Cat(name: String, val indoor: Boolean) : Animal(name)mainの中では:
val pets: List<Animal> = listOf(Dog("Rex"), Cat("Tom", true), Animal("Generic"))
for (p in pets) println(p.describe())出力:
Rex is an animal
Tom is an animal
Generic is an animal継承は「is-a」の関係を表します。犬は動物であり、普通預金口座は口座です。あるクラスが別のクラスを利用するだけの場合(車はエンジンを持つなど)は、その型のプロパティを持たせます。Kotlinではクラスはデフォルトで継承できないため、拡張を意図したクラスは open を付けて明示し、それ以外のクラスはサブクラスによる変更から安全に保たれます。
open class Account(val owner: String)
class SavingsAccount(owner: String) : Account(owner) // is-a: 継承
class Engine(val horsepower: Int)
class Car(val engine: Engine) // has-a: プロパティチャレンジ
簡単Managerは、Employeeがすでに持っているものを繰り返しています。Employeeをopenにし、Managerをそのサブクラスにしましょう。Manager(name: String, salary: Int)は両方の値をEmployeeに渡し、新たに加わるものだけを保持します。それは、報告対象者の名前を格納するprivateリストと、addReport(name)およびteamSize()です。Employeeでは、raise(percent)は給与をその割合だけ切り捨てで増やし、describe()はAda earns 5500を返します。
用意されたコードは、最初の行(name,salary)からマネージャーを作成し、後続の各名前を報告対象者として追加し、10%の昇給を行ってAda earns 5500 and leads 2を出力し、その後、マネージャーがEmployeeであることを確認します。
コードはEmployee.ktとManager.ktに記述します。Main.ktには用意された入出力コードがあり、編集できません。
自分で試してみよう
fun main() {
// 用意された入出力コード: そのままにしてください
val input = generateSequence(::readLine).toList()
val (name, salary) = input[0].split(",")
val boss = Manager(name, salary.toInt())
for (report in input.drop(1)) boss.addReport(report)
boss.raise(10)
println("${boss.describe()} and leads ${boss.teamSize()}")
println("a manager is an employee: ${(boss as Any) is Employee}")
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Kotlinプレイグラウンド