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

2016/12/28の30分 Kotlinメモ🐮

Kotlin

2016/12/28の30分 Kotlinメモ🐮

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

ざっくりKotlinの概要は終わったので、Androidアプリ組んでみるところ読んでる。

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

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

んで、今日からはKotlinでAndroid版 雑雑Qiita Clientを作っていく。

github.com

書くことは減りそうだけど、書いていく上で気づいたこととかあれば書いていくかなー

Kotlin版 BindableAdapter

ListAdapterを便利にするBaseクラスとして使ってるBindableAdapterをKotlinで書き直した。

abstract class BindableAdapterKt<T>(context: Context, episodeList: List<T>) : ArrayAdapter<T>(context, -1, episodeList) {

    private val inflater by lazy {
        LayoutInflater.from(context)
    };

    override fun getView(position: Int, view: View?, parent: ViewGroup?): View? {
        val newView = view ?: newView(inflater, position, parent)
        newView ?: throw IllegalStateException("newView result must not be null.")
        bindView(getItem(position), position, newView)
        return newView
    }

    abstract fun newView(inflater: LayoutInflater, position: Int, container: ViewGroup?): View?

    abstract fun bindView(item: T, position: Int, view: View)
}

エルビス演算子使えばいいのかなー?とかなんとなくKotlinっぽく書く努力をした結果がこれ。

ちゃんとSmart Castも使ってるよ?やるでしょ?

Java版はこんな感じ。

public abstract class BindableAdapter<T> extends ArrayAdapter<T> {
    private LayoutInflater mInflater;

    public BindableAdapter(Context context, List<T> episodeList) {
        super(context, -1, episodeList);
        setup(context);
    }

    private void setup(Context context) {
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public final View getView(int position, View view, ViewGroup container) {
        if (view == null) {
            view = newView(mInflater, position, container);
            if (view == null) {
                throw new IllegalStateException("newView result must not be null.");
            }
        }
        bindView(getItem(position), position, view);
        return view;
    }

    public abstract View newView(LayoutInflater inflater, int position, ViewGroup container);

    public abstract void bindView(T item, int position, View view);
}

まとめ

実際にコード書き始めるとめっちゃJavaっぽく書いてしまって...あとセミコロンな!

2016/12/27の30分 Kotlinメモ💤

Kotlin

2016/12/27の30分 Kotlinメモ💤

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

github.com

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

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

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

Equality

kotlinlang.org

=====の話ね。

// a?.equals(b) ?: (b === null)
val sssss: String? = null
val sssss2: String? = null
println(sssss == sssss2) // true

val sssss3: String? = "test"
println(sssss == sssss3) // false

val sssss4: String? = "test"
println(sssss4 == sssss3) // true

val iiii = 127
val iiii2 = iiii
println(iiii === iiii2) // true
println(iiii !== iiii2) // false
println(listOf("test") === listOf("test")) // false

まとめ

うむ、明日からKotlinでAndroid書いていくぞい💤

2016/12/26の30分 Kotlinメモ🍙

Kotlin

2016/12/26の30分 Kotlinメモ🍙

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

github.com

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

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

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

Type projections

kotlinlang.org

説明すると難しいし、俺もまだあまり理解できてないというか、これでいいのかな?レベルなのでなんともー

とりあえずoutinがあり、不変、共変、反変ということを理解すればいいかも。

Tって普通に書くと不変であり、サブタイプの関係は成り立たないらしい。

面倒そうだけど、安全な気がするねー。

class Container5<T>(var value: T) {
    fun copyTo(to: Container5<in T>) {
        to.value = value
    }
}

class Container6<out T>(val value: T) {
}

fun show(container5: Container5<out Any>) {
    println(container5.toString())
    println(container5.hashCode())
    println(container5.value)
}

fun show6(container6: Container6<Any>) {
    println(container6.toString())
    println(container6.hashCode())
    println(container6.value)
}

val c5: Container5<Number> = Container5(10)
Container5(10).copyTo(c5)
show(c5)

val c6: Container6<Number> = Container6(10)
show6(c6)

Star-projections

*ね。

Star-projectionsとかなんかジョジョっぽくね?かっくいいー!!

val c52: Container5<*> = Container5(10)
c52.value.toString() // Any?型になる

Reified type parameters

kotlinlang.org

あーこれねー

Javaで困るやーつーだな

Kotlinだと楽なんだなーいいなー

// inline + reified
inline fun <reified T> Any.instanceOf(): Boolean = this is T

println("".instanceOf<String>()) // true
println("".instanceOf<Int>()) // false

まとめ

ねぇ?Kotlin。そろそろ僕に心を開いてくれてもいいんじゃないかな?ね?

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

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メモ⚡

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について書いてあるけど、実際にそういうケースに出くわしたことがない気がするので割愛。

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

まとめ

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