2016/12/25の30分 Kotlinメモ🍰

2016/12/25の30分 Kotlinメモ🍰

書いてるコードは雑にここにあります。

github.com

Kotlinスタートブック -新しいAndroidプログラミング を引き続き読んでる。

Kotlinスタートブック -新しいAndroidプログラミング

Kotlinスタートブック -新しいAndroidプログラミング

Class Delegation

kotlinlang.org

前も書いたけど、これはよい。

そしてinterfaceのメソッドの引数にもデフォルト引数使えるんだーという発見。

interface GreeterKai {
    // sayHello()で呼び出すとデフォルト引数の方じゃなくて、引数なしで定義したメソッドが呼ばれるF
    fun sayHello()

    // デフォルト引数は指定できるのね
    fun sayHello(target: String = "匿名")
}

class JapaneseGreeterKai : GreeterKai {
    override fun sayHello() {
        sayHello("匿名")
    }

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

class GreeterWithRecording(private val greeterKai: GreeterKai) : GreeterKai by greeterKai {
    private val _target: MutableSet<String> = mutableSetOf()

    val targets: Set<String>
        get() = _target

    override fun sayHello(target: String) {
        _target += target
        greeterKai.sayHello(target)
    }
}

val gr = GreeterWithRecording(JapaneseGreeterKai())
gr.sayHello("test") // こんにちは、test!
gr.sayHello() // こんにちは、匿名!
gr.sayHello("kotlin") // こんにちは、kotlin!
println(gr.targets) // [test, kotlin]

Generics

kotlinlang.org

今のところ出てきたものはJavaとそこまで変わらず。

whereがちょっと変わってるかなー?みたいなところかねー

class Container<T>(val value: T) {
}

// Javaで書く T extends Collection<String>
 class Container2<T : Collection<String>>(val value: T) {
}

class Container3<T>(val value: T)  where T : Collection<String>, T : List<String> {
}

interface A {
}

interface B {
}

class Container4<T>(val value: T)  where T : A, T : B {
}

まとめ

メリークリスマス🍰

2016/12/24の30分 Kotlinメモ⚡

2016/12/24の30分 Kotlinメモ⚡

書いてるコードは雑にここにあります。

github.com

Kotlinスタートブック -新しいAndroidプログラミング を引き続き読んでる。

Kotlinスタートブック -新しいAndroidプログラミング

Kotlinスタートブック -新しいAndroidプログラミング

Interfaces

kotlinlang.org

デフォルト実装が持てるのと、プロパティ(も持てるのが興味深い。

プロパティもabstractなものと、デフォルトなものが持てると。

interface GreeterKai {
    // プロパティも持てる(プロパティ自体が値を持つものは宣言できない = varは無理.val)
    // 固定値 or 他のプロパティなら返せる
    val hum: String
        get() = "hum"

    // デフォルト実装を持てる
    fun hum() {
        println(language)
    }

    val language: String
    fun sayHello(target: String)
}

実装するとこんな感じ。

class EnglishGreeterKai : GreeterKai {
    override val language = "English"

    override fun sayHello(target: String) {
        println("Hello $target!")
    }
}

interfaceの継承

interfaceは別のinterfaceを継承することができると。

ここでもプロパティの扱いがどうなるか見てみた。

interface内ではやっぱりプロパティは値を持てないのね。

interface Homu {
    val homu1: Int
    var homu: Int
    fun homu()
}

interface Humu : Homu {
    // interface内のプロパティは値を持てない(バッキングフィールドを持てない)
    // 他のinterfaceが持つプロパティをoverrideしても、返せるのは固定値 or 他のプロパティ
    override val homu1: Int
        get() = 0

    fun humu()
}

ちなみにResolving overriding conflictsについて書いてあるけど、実際にそういうケースに出くわしたことがない気がするので割愛。

出くわした場合でもそんな難しいことではないしねー。

まとめ

いかんせんプロパティの扱いになれないですなー...⚡

2016/12/23の30分 Kotlinメモ😏

2016/12/23の30分 Kotlinメモ

書いてるコードは雑にここにあります。

github.com

Kotlinスタートブック -新しいAndroidプログラミング を引き続き読んでる。

Kotlinスタートブック -新しいAndroidプログラミング

Kotlinスタートブック -新しいAndroidプログラミング

Extension Properties

kotlinlang.org

プロパティも拡張できるのか。便利だなーまったく!!

// 拡張プロパティ
// バッキングフィールドは持てない
val String.countWords: Int
    get() = split("""\s+""".toRegex()).size

println("Kotlin Kotlin Kotlin!!".countWords) // 3

継承

kotlinlang.org

継承していいものにopenつけろよ!ってところ以外はだいたいJavaと同じかなー。

プロパティもoverrideできるのか!?ってことには驚いた!できるのか、そうか。

open class Person(val name: String) {

    open var age: Int = 0

    open fun introduce() {
        println("I am $name2.")
    }
}

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

    override var age: Int = 0
        get() = field
        set(value) {
            field = value * 2
        }

    override fun introduce() {
        println("I am $name(id=$id).")
    }
}

// super classの型にsub classの型は入る
val p2: Person = Student("kotlin", 1L)
p2.introduce()

Abstract Classes

これはほぼJavaと同じかなー

そしてプロパティをabstractにできるのか!?できるのか、そうか。

abstract class Greeter(val target: String) {

    abstract var code: String

    abstract val age: Int

    abstract fun sayHello()
}

class EnglishGreeter(target: String, override val age: Int) : Greeter(target) {
    override var code: String = ""
        get() = "en"
        set(value) {
            field = value
        }

    override fun sayHello() {
        println("Hello $target!")
    }
}

class JapaneseGreeter(target: String, override val age: Int) : Greeter(target) {
    override var code: String = ""
        get() = "ja"
        set(value) {
            field = value
        }

    override fun sayHello() {
        println("こんにちは、$target!")
    }
}

まとめ

冬休みもKotlinガンバルぞい!

2016/12/22の30分 Kotlinメモ🎲

2016/12/22の30分 Kotlinメモ🎲

書いてるコードは雑にここにあります。

github.com

Kotlinスタートブック -新しいAndroidプログラミング を引き続き読んでる。

Kotlinスタートブック -新しいAndroidプログラミング

Kotlinスタートブック -新しいAndroidプログラミング

Properties and Fields

kotlinlang.org

プロパティはあくまで窓口であり、実際に値を保持するBacking Fieldにはプロパティ内部でしかアクセスできないと。

Backing Field = 実際の値の参照を保持するもの?みたいな?

class Person {

    var name: String = ""
        set(value) {
            println("set $value")
            // field = バッキングフィールドを表す暗黙の変数
            field = value
        }
    var age: Int = 0
}

以下のnameLengthプロパティはBacking Fieldは生成されない。

class Person {

    var name: String = ""
        set(value) {
            println("set $value")
            // field = バッキングフィールドを表す暗黙の変数
            field = value
        }
    var age: Int = 0
    val nameLength: Int
        get() = name.length
}

Javaをやってて、プロパティ謎いぞ!フィールドと何が違うの!ってなったけど、@sys1yagiさんが書いてる以下を読んだら納得できた。

バッキングフィールド?なんだそれ?となったら、読んでみるとよい。

5. プロパティの正体 · Anatomy Kotlin

Late-Initialized Properties

kotlinlang.org

Backing Fieldを持つプロパティは必ず初期化する必要があるけど、lateinitをつければ初期化タイミングを遅らせることができるよ!ってことらしい。

使用できるプロパティに色々制限はあるので、用途は限られそう。

class Person {
    // 初期化のタイミングを遅らせる
    // varでしか使えない + non nullでしか使えない + primitiveには使えない + custom getter/setterは持てない
    // https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties
    // DIとかに使える
    // 初期化する前にアクセスするとUninitializedPropertyAccessExceptionが起きる
    lateinit var humuhumu: String
}

val p = Person()
//    println(p.humuhumu) // kotlin.UninitializedPropertyAccessException: lateinit property humuhumu has not been initialized
p.humuhumu = "humuhumu"
println(p.humuhumu) // humuhumu

まとめ

プロパティの謎が少しずつわかってきたのでたのしいたのしい🎲

2016/12/21の30分 Kotlinメモ🍥

2016/12/21の30分 Kotlinメモ🍥

書いてるコードは雑にここにあります。

github.com

Kotlinスタートブック -新しいAndroidプログラミング を引き続き読んでる。

Kotlinスタートブック -新しいAndroidプログラミング

Kotlinスタートブック -新しいAndroidプログラミング

Object Expressions

kotlinlang.org

objectね!

なんか色々できるので、どんな用途で使うのがいいんだろーと悩む🤔

きっといつか答えが出るだろう...!

Interface

kotlinlang.org

Javaと基本同じだけど、プロパティを持てることに驚いたぞ!!

interface BucketKai {
    fun fill()
    fun drainAway()
    fun pourTo(that: BucketKai)

    // interfaceはプロパティを持てる
    // プロパティはオブジェクトの内部にあるものではなく、境界にあるもの
    // 変数のように見えるが、実際のデータの持ち方は規定しない
    // 実装するオブジェクトの実装次第になる
    val capacity: Int
    var quantity: Int
}

オブジェクト式で生成するとこんな感じで実装して使える。

fun createBucketKai(_capacity: Int): BucketKai = object : BucketKai {

    // プロパティにもoverrideがつく
    override val capacity = _capacity

    // プロパティは必ず初期化しないといけない
    override var quantity = 0

    override fun fill() {
        quantity = capacity
    }

    override fun drainAway() {
        quantity = 0
    }

    override fun pourTo(that: BucketKai) {
        val thatVacuity = that.capacity - that.quantity
        if (quantity <= thatVacuity) {
            that.quantity = quantity
            drainAway()
        } else {
            that.fill()
            quantity -= thatVacuity
        }
    }
}

val bucketKai1 = createBucketKai(7)
val bucketKai2 = createBucketKai(4)

bucketKai1.fill()
bucketKai1.pourTo(bucketKai2)
println(bucketKai1.quantity) // 3
println(bucketKai2.quantity) // 4

Class

上で使ったInterface BucketKaiをクラスで実装するとこんな感じ。

class BucketImpl(override val capacity: Int) : BucketKai {

    override var quantity = 0

    override fun fill() {
        quantity = capacity
    }

    override fun drainAway() {
        quantity = 0
    }

    override fun pourTo(that: BucketKai) {
        val thatVacuity = that.capacity - that.quantity
        if (quantity <= thatVacuity) {
            that.quantity = quantity
            drainAway()
        } else {
            that.fill()
            quantity -= thatVacuity
        }
    }
}

まとめ

どの絵文字使ってないか忘れてきたぞい...🍥