LoginSignup
11
13

More than 5 years have passed since last update.

Kotlinまとめ - 文法詳解 - 継承と抽象クラス

Last updated at Posted at 2018-07-24

クラスの継承

  • インタフェースに準拠するときと同じように、クラス名の定義の後に:でつなげる
  • 継承元:スーパークラス、継承先:サブクラス
  • 継承元のクラスはopenを指定しないと継承不可
open class Person(val name: String) {
    fun introduceMyself() {
        println("I am $name")
    }
}

class Student(name: String, val id: Long): Person(name)

メンバのオーバーライド

  • オーバーライドもデフォルトで禁止されており、プロパティやメソッドにopenを付ける必要がある
  • スーパークラスのメンバを呼び出すときはsuper.メンバ
open class Person(val name: String) {
    open fun introduceMyself() {
        println("I am $name")
    }
}

class Student(name: String, val id: Long): Person(name) {
    override fun introduceMyself() {
        super.introduceMyself()
        println("id=$id")
    }
}

val student = Student("hicka04", 123)
student.introduceMyself()  // I am hicka04 \n id=123

スーパータイプとサブタイプ

  • クラスを定義することで型を得られる
    • スーパークラス:スーパータイプ
    • サブクラス:サブタイプ
  • サブタイプのオブジェクトは、スーパータイプのオブジェクトとして扱うことができる
    • スーパータイプにないメンバはアクセス不能
    • アクセスすると実態はサブタイプの方にアクセスしている
val person: Person = Student("hicka04", 123)
person.introduceMyself()  // I am hicka04 \n id=123
person.id  // コンパイルエラー

Any

  • すべてのクラスが継承している暗黙的な型
  • すべてのオブジェクトに共通する基本的なメソッドを提供している
public open fun toString(): String
public open operator fun equals(other: Any?): Boolean
public open fun hashCode(): Int

抽象クラス

  • メンバのオーバーライドをサブクラスに強制する仕組み
  • メソッドやプロパティにabstructをつける → 抽象メンバ
  • 抽象メンバをもつクラスは抽象クラスで、インスタンス化はできない
  • abstructがついている抽象メンバはオーバーライド必須なのでopenキーワードは不要
abstract class Greeter(val target: String) {
    abstract fun sayHello()
}

class EnglishGreeter(target: String): Greeter(target) {
    override fun sayHello() {
        println("Hello, $target")
    }
}

class JapaneseGreeter(target: String): Greeter(target) {
    override fun sayHello() {
        println("こんにちは、$target")
    }
}

EnglishGreeter("Kotlin").sayHello() // Hello, Kotlin
JapaneseGreeter("Java").sayHello()  // こんにちは、Java

可視性

パッケージ

  • Javaと同様にパッケージで名前空間を区切る
  • パッケージ直下には以下の要素を宣言できる
    • 関数
    • プロパティ
    • クラス
    • インタフェース
    • オブジェクト
  • 同一のパッケージ内に同名のクラスを複数定義することはできない
    ⇔異なるパッケージであれば同名のクラスを定義可能
package sample.hoge
class Foo
  • Foosample.hogeに属する
    • 完全修飾名はsample.hoge.Foo
  • 同一パッケージ内であればFooでアクセス可能
  • 異なるパッケージから呼ぶときはsample.hoge.Fooでアクセスする必要がある
    • importすることでFooだけで呼べるようになる
package sample.fuga
import sample.hoge.Foo
import sample.fuga.Buz as Beer
class Baz

class Bar {
    fun doSomething() {
        sample.hoge.Foo()
        Foo()  // importしてるのでこれでOK
        Berr() // 別名インポートしているのでOK
    }
}

トップレベルにおける可視性修飾子

  • パッケージ直下に宣言できる関数やクラスなどに可視性修飾子をつけることで公開範囲を調整できる
修飾子 公開範囲 備考
public 公開範囲に制限はなく、どこからでもアクセス可 デフォルト
internal 同一のモジュール内に限り全公開
private 同一ファイル内のみアクセス可能

クラスにおける可視性修飾子

クラスやインタフェースのメンバにつける可視性修飾子

修飾子 公開範囲 備考
public 公開範囲に制限はなく、どこからでもアクセス可 デフォルト
internal 同一のモジュール内に限り全公開
protected 同一クラス内とサブクラス内からアクセス可
private 同一クラス内のみアクセス可能
// プライマリコンストラクタにつけるときは`constructor`を省略できない
open class Hoge private constructor()

← 文法詳解 - クラスとそのメンバ || 文法詳解 - インタフェース →

11
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
13