読者です 読者をやめる 読者になる 読者になる

2016/12/05の30分 Kotlinメモ🌵

2016/12/05の30分 Kotlinメモ🌵

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

github.com

Nested Classes

kotlinlang.org

インナークラスね。そこまでJavaと違いはないかな。

メソッドの中にメソッド定義できるのかー。

class Nest {

    private val a = "a"

    class Test {
        fun test() = "test"

        fun test2(): String {
            // メソッドの中でクラス定義もできる
            class Test3(val s: String) {
            }
            Test3("test").s

            // メソッドもネストしてローカル関数として定義できる
            fun test3(s: String): String {
                return s + " test3"
            }

            return test3("test2")
        }
    }

    // innerをつけると内部クラス
    inner class Test2 {
        fun test() = a
    }
}

Enum

kotlinlang.org

まあ普通のEnumだね。

enum class Status {
    OPEN, RUNNING, CLOSE,
}

enum class Color(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF)
}

enum class ProtocolState {
    // WAITINGはProtoclStateを継承してsignal()をオーバーライドした無名クラスのインスタンス
    WAITING {
        override fun signal() = TALKING
    },

    TALKING {
        override fun signal() = WAITING
    };

    abstract fun signal(): ProtocolState
}

ほむほむ。名前と位置の情報を持ってるのか。使うのかな?

Every enum constant has properties to obtain its name and position in the enum class declaration

val name: String
val ordinal: Int

println(Color.RED.name) // RED
println(Color.RED.ordinal) // 0

Sealed Classes

kotlinlang.org

taro.hatenablog.jp

クラスの継承を制限するための修飾子?なのかな?

// sealedを付けられたクラスを継承できるのは、その内部クラスだけ
sealed class TaskStatus {
    class New(val id: Long) : TaskStatus()
    class Running(val id: Long, val date: String) : TaskStatus()
    class Close(val id: Long, val close: Boolean) : TaskStatus()
    object None : TaskStatus()
}

whenで使うといい感じなのかな?

状態の表現 + whenという組み合わせて、なんかできそうかも。

fun states(taskStatus: TaskStatus): String = when (taskStatus) {
    is TaskStatus.New -> "new"
    is TaskStatus.Running -> "run"
    is TaskStatus.Close -> "close"
    TaskStatus.None -> "none"
}

val new = TaskStatus.New(0)
val run = TaskStatus.Running(0, "test")
val close = TaskStatus.Close(0, true)
val none = TaskStatus.None

println(states(new)) // new
println(states(run)) // run
println(states(close)) // close
println(states(none)) // none

when式の分岐でelseがない = sealed classとして定義されており、他の場所でそのサブクラスが定義されないことを保証してる。なので、when式の分岐ですべての場合が考慮されていることをコンパイラは知っているのでelseが不要みたいなことがtaroさんのブログに書いてあって、なるほどーとなった。

まとめ

思った以上にenumが普通で残念かなーSwiftみたいな感じがいいなー

Sealed Classesで似たような感じになるのかなー

4つと5つ値を持つTupleを作ってみた - 2016/12/04の30分 Kotlinメモ💪💪💪💪💪

Kotlin

4つと5つ値を持つTupleを作ってみた - 2016/12/04の30分 Kotlinメモ💪💪💪💪💪

主に前回書いた内容の発展系 + マッスル系💪

hack-it-iron.hatenablog.com

とある事情からJava Tupleのライブラリを作ってるわけですが、Kotlinは3つまで値を持つTuple(Triple)までは標準ライブラリで提供されてます。

記事を見てると、Kotlinも昔はもっと値がいっぱいあるTupleを標準で用意されていたらしいですが、どこかのタイミングでなくなったみたいですね。

なのでそこについては詳しく触れないっす。

あ、ちなみにこれが私が作ってるJava TupleライブラリのGuildです。

github.com

もっと筋肉💪 つけたいよね?

そうなんだよ。もっと値を入れられるTupleがほしいんだよ。

ということで、標準ライブラリにあるTupleを参考に4つと5つ値を持つTupleを作ってみた。

今回紹介するコードは以下のリポジトリに雑に置いてあります。

github.com

4つの値を持つTuple Quartetを作る

ネーミングセンスはjavatuplesというライブラリから拝借してます。

ざっくり書いてこんな感じ。Quartet自体はただの入れ物なので実装はシンプルでよい。

data class Quartet<out F, out S, out T, out FO>(
        val first: F,
        val second: S,
        val third: T,
        val fourth: FO) {

    override fun toString(): String {
        return "Quartet(first=$first, second=$second, third=$third, fourth=$fourth)"
    }
}

んで、前回の記事にこんなことを書きました。

Kotlinには4つ以上のTupleはないけど、自分で作って1つ値が少ないクラスに拡張関数を書けば、A to B to C to Dもできるわけだ

うむ、じゃやってみよう。

A to B to C to Dと書いてQuartetを作りたいので、TripleからQuartetを作る拡張関数を書きます。

infix fun <A, B, C, D> Triple<A, B, C>.to(that: D): Quartet<A, B, C, D> = Quartet(this.first, this.second, this.third, that)

んまーPairからTripleを作る時に書いた拡張関数を応用してあげればよい。

んで、以下のような感じでA to B to C to Dって感じで書いてあげれば、Quartetが作れる。

println(("b" to 2 to 2 to 10L))
println(("b" to 2 to 2 to 10L).javaClass)

■出力
Quartet(first=b, second=2, third=2, fourth=10)
class Quartet

もっと筋肉がほしいだろ💪💪💪💪💪 5つの値を持つTuple Quintetを作る

もうこいつは番外編です...💪💪💪💪💪

はい、実装はこんな感じね。

data class Quintet<out F, out S, out T, out FO, out FI>(
        val first: F,
        val second: S,
        val third: T,
        val fourth: FO,
        val five: FI) {

    override fun toString(): String {
        return "Quintet(first=$first, second=$second, third=$third, fourth=$fourth, five=$five)"
    }

A to B to C to D to Eと書いてQuintetを作りたいので、QuartetからQuintetを作る拡張関数を書きます。

infix fun <A, B, C, D, E> Quartet<A, B, C, D>.to(that: E): Quintet<A, B, C, D, E> = Quintet(this.first, this.second, this.third, this.fourth, that)

あー筋肉💪が増えるごとにコードが長くなっていく...

んで、以下のような感じでA to B to C to D to Eって感じで書いてあげれば、Quintetが作れる。

println(("b" to 2 to 2 to 10L to "D"))
println(("b" to 2 to 2 to 10L to "D").javaClass)

■出力
Quintet(first=b, second=2, third=2, fourth=10, five=D)
class Quintet

まとめ

toをつなげて書いてTupleが作れるのは嬉しいなー

いくらでも筋肉💪がほしくなる。

ちなみにKotlinのGenerics周りがちょっとJavaと違いそうだなーと思ったので、今後それも学んでいきたい。

kotlinlang.org

outとか使ってみたけどまだちゃんと理解してないねー

PairからTripleを作る拡張関数を書いてみた - 2016/12/03の30分 Kotlinメモ🙈

Kotlin

PairからTripleを作る拡張関数を書いてみた - 2016/12/03の30分 Kotlinメモ🙈

今回紹介したコードとかは以下のリポジトリに雑に置いてあります。 

github.com

toを3つ以上繋げて書いたらどうなるのか

KotlinにPairがあって、toを3つ以上繋げて書いたらどうなるのかなーとやってみた。

kotlinlang.org

println(("b" to 2 to 2))
println(("b" to 2 to 2).javaClass)

■出力
((b, 2), 2)
class kotlin.Pair

ほむほむ。なるほど。Pair in Pairみたいな感じになるのね。

Pair<Pair<b,2>,2>ってことか。

あれれ?確かTripleってあったよな?

あるね。

kotlinlang.org

俺的にはA to B to Cって書いたら、Tripleになるのかなーとか思ってたけど、そうじゃないみたい。

残念。。。まあInfixには1つの引数しか指定できないからしょうがないかーと思った。

けど、Pairに拡張関数を作ればTripleにできるんじゃね?と思って、PairからTripleを作る拡張関数を書いてみた。

infix fun <A, B, C> Pair<A, B>.to(that: C): Triple<A, B, C> = Triple(this.first, this.second, that)

んまー、こんな感じかな?

んじゃ、Pair in Pairになってたやつと同じ処理を動かしてみるとー

println(("b" to 2 to 2))
println(("b" to 2 to 2).javaClass)

■出力
(b, 2, 2)
class kotlin.Triple

うむ!A to B to Cと書いて、ちゃんとTripleになってる!成功だーやたー

Kotlinには4つ以上のTupleはないけど、自分で作って1つ値が少ないクラスに拡張関数を書けば、A to B to C to Dもできるわけだ。

まとめ

拡張関数 使い方に慣れてくるとよいなー

2016/12/02の30分Kotlinメモ🔥

Kotlin

2016/12/02の30分Kotlinメモ🔥

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

github.com

関数

kotlinlang.org

デフォルト引数いいねー。

Named Argumentsもできるので、便利だ。

fun testFun(test: String = "", value: Boolean = true, intV: Int = 1) {
    println(test)
    println(value)
    println(intV)
}

testFun()
testFun("test")
testFun("test", intV = 9)
testFun(value = false)

Properties

kotlinlang.org

これはなんか色々あるので、使って理解していくしかなさそう。

open class User(open val name: String) {

    var gender: Int = 0
        set(value) {
            field = value
        }

    val isAdmin: Boolean
        get() = false
}

プロパティのoverrideもできるのか。なるほど。

class AdminUser(name: String) : User(name) {

    override val name: String
        get() = name.toUpperCase()
}

Interfaces

kotlinlang.org

デフォルト実装もできるので、Java 8に似てるなー。よい。

interface Action {

    // propertyを持てる.interface側では値を設定できない
    val prop: Int

    val name: String
        get() = "action name"

    fun jump()

    // デフォルト実装を持てる
    fun run() {
        println("run")
        println(prop)
        println(name)
    }
}

class TestAction : Action {
    override val prop: Int = 1

    override val name: String
        get() = super.name + " test"

    override fun jump() {
        println("TestAction jump")
    }
}

Visibility Modifiers

kotlinlang.org

何もつけないとpublicになる。なるほど。

ちょっとJavaと違うので、これは使いながら学ぶしかなさそう。まだはっきりわかってない。

package test

// 何もつかないとpublic
class Event {

    // 値の参照はできるが、setterはこのファイル内からしかできない
    var value = 0
        private set

    internal val name = "test"

    private fun test() {
        value = 10
    }
}

まとめ

うむ、よい。当たり前のことが当たり前にできる喜び。

2016/12/01の30分Kotlinメモ😎

Kotlin

2016/12/01の30分Kotlinメモ😎

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

github.com

Collections

mutableとimmutableのcollectionsが分かれてる。

kotlinlang.org

List

要素は配列みたいに[index]とかでアクセスできる。

set(index)で書いたら、IDE[index]の方で書いたほうがいいよーって書き直されたので、そっちの記法で書くのがいいのかなーと勉強になった。

確かにやってることは同じだし、一々setとかメソッド名書くのだるいか。

val ml: MutableList<String> = mutableListOf("a", "b")

ml[0] = "c" // ml.set(0, "c")
println(ml[0]) // c

+=とか-=とかで要素を追加したり、削除したりできる。

便利ー。operator overrideやっぱりいいなー。

ml += "d" // plusAssign
println(ml) // [c, b, d]

ml -= "d" // minusAssign
println(ml) // [c, b]

Map

Pairにして渡すのねー

List同様で[key]で値にアクセスできるので便利だ。

val map2 = mutableMapOf("a" to 1, "b" to 2) // value to value でPairの生成
println(map2)
println(map2["a"])

List同様で+=で要素追加できる。

map2 += "c" to 3
println(map2) // {a=1, b=2, c=3}

println(("b" to 2 to 2 to 1)) // (((b, 2), 2), 1)
println(("b" to 2 to 2 to 1).javaClass) // class kotlin.Pair

Range

Javaにはないrangeね。これは便利だよねー。

kotlinlang.org

IntRangeCharRangeLongRangeがあるっぽい。自分でも独自の型でRange作れるのかなー?

// range
println(5 in 1..10)
val range: IntRange = 1..10
val cRange = 'a'..'z'
val lRange = 10L..100L
println(5 in range)
println(5 !in range) // !in = 範囲外

toListとかでRangeからListにできる。なるほど。

逆順ならdownTo、一定間隔にしたいならstep

println((1..5).toList())
println((5 downTo 1).toList()) // [5, 4, 3, 2, 1]
println((1..5 step 2).toList())
println((100 downTo 0 step 25).toList()) // [100, 75, 50, 25, 0]

if

基本はJavaと同じ。

最後に書いた値が戻り値になる。returnとかいらないのは楽。

val a = 1
val b = 2

val c = if (a > b) {
    println(a)
    a
} else {
    println(b)
    b
}
println(c) // 2

こんな感じでも書ける。三項演算子はないのよね。

val d = if (true) "true" else "false"
println(d) // true

こんな感じでも書ける。便利そう。

val aaaa = 10
var e =
        if (aaaa == 10) "10"
        else if (aaaa > 2) "2"
        else "0"
println(e) // 10

when

こいつがとにかく便利。

kotlinlang.org

switchみたいだけど、メソッドの戻り値を指定できる。定数じゃなくていいのか。Goみたいだ。

when (10) {
    hogehoge() -> println("hogehoge")
    1 -> println("a")
    2 -> println("a")
    3 -> println("b")
    else -> println("else")
}

RangeやListも指定できる。List内に含まれていたら...って感じになる。最高。

when (1) {
    in list -> println("list")
    0, 1 -> println("0 or 1")
    in 2..10 -> println("range 2..10")
}

値を返したり、ifみたいな感じでも書けるのですごい!

// 値が返せる
val aa = when (1) {
    1 -> 1 * 3
    else -> 0
}
println(aa) // 3

// ifみたいに書ける
when {
    "s".isEmpty() -> println("empty")
    else -> println("else")
}

val aaaa = 10

val e = when {
    (aaaa == 10) -> "10"
    (aaaa > 2) -> "2"
    else -> "0"
}
println(e) // 10

まとめ

rangeとwhenがとにかくすごい