- 作者: 長澤太郎
- 出版社/メーカー: リックテレコム
- 発売日: 2016/07/13
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
やろうやろう詐欺をし続けて、結構時間が経ったので本腰を入れていく。kotlinだけでなくAndroidのライブラリ全般で開発がめちゃくちゃ早いので、一年前の本なのに読んでみたはいいけどかなりの部分がもう古い情報になっているので注意。読めば「なるほど〜」となるが手を動かすのが重要。サンプルアプリを作るところまでがこの本のゴールなので作ったはいいが、Dagger周りで仕様変更が大きすぎて公開するにはもう少し直さないといけない。
※2017/08/03追記 シンプルにDagger2.11を使って実現したので、サンプルを公開した。サブコンポーネントはややこしいので使ってない。
基本的には冗長なnullチェックがなくなるってインパクトが強いけど、正確には nullをしっかり区別して、簡潔に書ける ところが素晴らしいなと感じる。 普通に書くだけでnullを意識しないとコンパイルできないのが強力だよなぁ。
newや;(セミコロン)は不要- コンストラクタの引数に
varやvalをつけるとgetterやsetterが生える require関数で初期値違反を検出する- tailrecは末尾再帰(tail recursive)
- 演算子オーバーロードが便利
- 拡張関数最高
kotlincコマンドでREPL起動- 原則として
valを使い、再代入不可にする - ${変数名}で値参照(同じリテラルなら中かっこ省略可能)
- 拡張関数の思いつき:toggle(Visibilityの反転)
+=とか-+とかで要素を追加、削除できるのよいlistOfで不変長リスト,mutableListOfで可変長リストtoでPairオブジェクトの作成が可能 ->val pair = ("key" to value)- Mapには
Pariオブジェクトを渡す必要がある - Stringは
toRegexで正規表現に変換可能 - 基底クラスは
Any。クラスとして定義したものは全てAnyのサブクラス - open修飾子で継承可能にできる
===で等価かどうか判別a.plus(b)をa plus bのようにする(中値呼び出し)にするにはinfix修飾子をメソッドにつけるrangeの代わりに[1..10]で使っている..もstep関数のinfix- 内部クラスにするには
inner修飾子をつける(アクセスが外側のオブジェクト経由でないとできなくなる) - 可変長引数にするには
varargで指定し、一つに関数に一つのみ - 返り値のない関数は
Unit ::で関数オブジェクトを取得(そしてそれを変数に代入やメソッドに渡せる! Function)- 関数オブジェクトを直接生成するのがラムダ式
->。中かっこ必須{}
val square: (Int) -> Int = { i: Int ->
i * i
}
//型推論による省略式
val square = { i: Int ->
i * i
}
//引数が一つのときのみ`it`が使える
val square: (Int) -> Int = {
it * it
}
リスト系
val range: IntRange = 12..15
inで存在確認
>>> 5 in range true >>> 5 !in range false
Listオブジェクトへの変換
(1..5).toList()
反転
//(1..5).reversed().toList() (5 downTo 1).toList()
等間隔
(0..100 step 25).toList() //[0,25,50,75,100]
オブジェクトと型クラス
object式
値と関数を持つオブジェクト
val bucket = object {
val capacity: Int = 5
val quantity: Int = 0
fun fill() {
quantity = capacity
}
fun drainAway() {
quantity = 0
}
fun printQuantity() {
pringln(quantity)
}
}
※単体では型がないため名前参照ができない
interface
型を与えることができる。名前参照が可能になる
interface Bucket {
fun fill()
fun drainAway()
fun pourTo(that: Bucket)
fun getCapacity(): Int
fun getQuantity(): Int
fun setQuantity(quantity: Int)
}
fun createBucket(capacity: Int): Bucket = object : Bucket {
var _quantity: Int = 0
override fun fill() {
setQuantity(getCapacity)
}
override fun drainAway() {
setQuantity(0)
}
//バケツに注ぐ
override fun pourTo(that: Bucket) {
val thatVacuity = that.getCapacity() - that.getQuantity()
if(getQuantity() <= thatVacuity) {
that.setQuantity(that.getQuantity() + getQuantity())
drainAway()
} else {
that.fill()
setQuantity(getQuantity() - thatVacuity)
}
}
override fun getCapacity(): Int = capacity
override fun getQuantity(): Int = _quantity
override fun setQuantity(quantity: Int) {
_quantity = quantity
}
}
SAM interface
Single Abstract Method interfaceはラムダに変換できる
Runnable : run()View.OnClickListener : onClick(View v)
などを次のように書ける。
view.setOnClickListener { v ->
//do something
}
クラス
バッキングフィールド
カスタムゲッター
プロパティにカスタムゲッターを設定することで
class Person {
var name: String = "" //プロパティ
var age: Int = 0 //プロパティ
val nameLength: Int //バッキングフィールドを持たないプロパティ
get() = this.name.length //カスタムゲッター
}
以上のようにすると
val hanako = Person() hanako.name = "はなこ" println(hanako.nameLength) // =3
となる。
カスタムセッター
プロパティへ
class Person {
var name: String = ""
set(value) { //カスタムセッター
println("${value}がセットされました")
field = value //fieldがbucking
}
var age: Int = 0
val nameLen: Int
get() = this.name.length
}
とすることで、値がセットされた時に処理を行える。
val test = Person() test.name = "test" //testがセットされましたを出力 println(test.nameLen) // =4
コンストラクタ
constructorキーワードでコンストラクタに引数を与えれる。それらをプロパティにセットする。
class Rational constructor(n: Int, d: Int) {
val numerator: Int = n
val denominator: Int = d
}
普通はconstructorキーワードを省略して、引数に直接valやvarをつけると同じ意味になる。
class Rational (val numerator: Int, val denominator: Int)
デフォルト値も設定可能。 デフォルト値を設定することでメンバ変数の初期化を書かなくてよい。
class Rational (val numerator: Int, val denominator: Int = 1)
イニシャライザも追加可能。
class Rational (val numerator: Int, val denominator: Int = 1) {
init {
require(denominator != 0)
}
}
requireは条件を満たさない時に例外を投げる関数
ジェネリクス
基本
class Container<T>(var value: T)
型制約
//単数 class Container<T: Hoge>(var value: T) //複数 class Container<T> where T : Hoge, T : Fuga
Null safety
いろんな書き方や制約のつけ方があるので、導入前にチームで話した方がいい。
最近lintも増えつつある。
チームでコード規約を作っていくのもいいと思う。
nullを代入
val s: String = null //コンパイルエラー val s: String? = Null
nullの可能性がある変数の参照
s.toUpperCase()//コンパイルエラー s?.toUpperCase()//nullでなければ実行される
引数がNotNullでないといけないメソッドなどはletを使う
fun square(i: Int): Int = i * i val a: Int? = 5 val aSquare = a?.let(::square)//引数が一つなので関数オブジェクトを渡せる
!!は使うな
val hoge: String? = null
val fuga: String = requireNotNull(hoge, {"ぬるぽ"}) //NPE
エルビス演算子?:
nullの時はデフォルトを使う的な実装をするときに使う
val foo: String? = "hello" (foo ?: "default").toUpperCase() //>>>HELLO val hoge: String? = null (hoge ?: "default").toUpperCase() //>>>DEFAULT
安全キャスト
ClassCastExceptionを防ぐ
val str: Any = "ぺろーん" str as String //ok str as Int // ClassCastException str as? Int //return null
その他
演算子オーバーロード
+は.plus()と等価のようにメソッドに演算子を対応づけられる。
対応させるにはoperator修飾子をつける
class MyInt(val value: Int) {
operator fun times(that: MyInt): MyInt = MyInt(value * that.value)
}
val product = MyInt(3) * MyInt(5)
product.value //=15
分解宣言
pairのfirstとsecondを別々に宣言してアクセスできるようにする方法
val (name, age) = Pair("Yuichi", 27)
println(name) //Yuichi
println(age) //27
データクラス
クラス宣言にdataをつけるとAnyクラスが持つメソッドの適切な実装が行われる。
これにより、toStringでデータを表示したり、equalsでの中身が同じかどうかの比較、
copyでJavaのcloneと同じように、ディープコピーが可能。
class User(val id: Long, val name: String) User(1, "you") == User(1, "you") //false --- data class User(val id: Long, val name: String) User(1,"you") == User(1, "you") //true
シングルトンにするには
classではなくobjectを使うと実現可能
object Me {
fun hello() {
println("Hello world")
}
}
- クラス内に作るときは
companion object修飾子をつける - コンパニオンオブジェクトは1クラスに1つ
enum
enum class SomeType(val num: Int) {
S(100) {
override fun message(): String = "small"
},
M(300) {
override fun message(): String = "medium"
},
L(500) {
override fun message(): String = "large"
};
abstruct fun message(): String
}
SomeType.S.num //100
SomeType.M.message() //medium
val types: Array<SomeType> = SomeType.values()
types.toList() //[S, M, L]
SomeType.valueOf("S") //S
SomeType.S.name //S
SomeType.values().map { type -> type.ordinal } //[0, 1, 2]
以上。
豪華執筆陣による「Kotlin入門までの助走読本」をリリースします!
— 日本Kotlinユーザグループ (@kotlin_jp) 2017年5月29日
話題のプログラミング言語の「味見」をぜひ!PDF注意https://t.co/LJJDReAzue
これから助走読本を読みつつ、公式が用意している try! kotlinのkoansも解く。
余談だけどkoansって中国の公案のことで、いわゆる禅問答のことだ。
悟りを開いていこう。