Kotlin 勉強メモ(Kotlin 入門までの助走読本)
まちカドまぞく面白いです。二回見る程度には面白いです。
最近、Android 開発できるようになろうとチマチマ勉強中です。過去に一度か二度勉強したのですが途中で挫折しました。でも今回は少しずつですが理解が進んでいる気がします。
Android 開発では、今や開発言語は Kotlin です。Android 開発しているのに Kotlin 知らない人なんていません。Google もAPI の提供を Kotlin 優先にするって言ってます。
だから Kotlin を勉強しています。
というのもありますが、単純に書いてて楽しいです。Kotlin
(もちろん、Android 開発は必ず Kotlin でするべきということではありません。環境によりけりです)
参考書籍
Kotlin を勉強するにあたって参考にした書籍は Kotlin 入門までの助走読本です。
プログラミング経験者が Kotlin を学ぶのに最適な本です。あまり詳細に踏み込まず、かといって浅すぎない。Kotlin がどんな言語かなんとなく理解できる良い本です。
過去に速習 Kotlin という本も読んだことがありますが、これよりも浅いように感じました。ただ、助走読本のほうは、Java からの移行や今後どうやって Kotlin を取り入れるかなどの情報もあるのでどちらの方が良いというのは決められないです。
速習 Kotlin: Javaより簡単!新Android開発言語を今すぐマスター 速習シリーズ
- 作者: 山田祥寛
- 出版社/メーカー: WINGSプロジェクト
- 発売日: 2018/09/26
- メディア: Kindle版
- この商品を含むブログを見る
まだ読んでいませんが、さらに Kotlin を知るなら Kotlin イン・アクションは必読だと思います。
- 作者: Dmitry Jemerov,Svetlana Isakova,長澤太郎,藤原聖,山本純平,yy_yank
- 出版社/メーカー: マイナビ出版
- 発売日: 2017/10/31
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
今回は、Kotlin 入門までの助走読本 を読んでメモしたことを羅列していきます。
はじめに
Kotlin の環境構築は IntelliJ IDEA をいれれば済むはずですが、それも面倒な場合、とにかく1秒でも早く実行したいという人は、Kotlin Playground(正式名称わかりません) がオススメです。
Kotlin Playground は、オススメですがたまに全然動かなくなります(実行しすぎ?)。片手間に IntelliJ IDEA を入れるのをオススメします。
(?)がついている箇所は深く検証していなくて不明確な部分です。
以下、Kotlin 入門までの助走読本のメモです。
変数
val
, var
で宣言します。
val
は変数の再代入が不可var
は変数の再代入が可- 型は省略可能
val num = 1 // val num: Int = 1 と同じ num = 2 // コンパイルエラー var num2: Int = 2 num2 = 4 // 可能
if 式
式としても文としても書けます。
val value = if (true) { 32 } else { 64 } // value = 32
when 式
switch のように書けます。
else
がないとコンパイルエラーになる- 左辺(左側)でも使える
val str = when (1) { 1 -> "one" 2 -> "two" else -> "other" } // str = "one"
for 文
for (i in 0..2) { print(i) } // 012
downTo
を使うと逆順になります
for (i in 2 downTo 0) { print(i) } // 210
step
を使うとその値で飛ばします(downTo
でも使えます)
for (i in 0..2 step 2) { print(i) } // 02
while
,do-while
もある
コレクション
reversed
で逆順になるreversed
とreversedArray
は、List
で返すか、Array
で返すかの違い(基本はreversed
で返す)ミュータブル
と読み取り専用
がある。基本は読み取り専用
読み取り専用
であって、イミュータブル
ではない
- 生成はファクトリ関数を使う
forEach
を使う場合、it
で要素にアクセスできる
以下が詳しいです。
null 許容型
型宣言で ?
を使うことで null 許容型
になります。デフォルトは null 非許容
です
val str: String? = null val value2 = str?.length // null が渡る println(value2) // null が出力される
- 値を渡す場合、受け取る側も
null 許容型
でないといけないnull
チェックが行われても型は変わらない(null 許容型
のまま)- ただし、
null
チェックのブロック内では、null 非許容型
として扱えるnull
の代入は可能
- ただし、
!! 演算子
null 許容型
を非許容型
に強制変換するが、危険requireNotNull
関数を検討すること
関数
fun double(a: Int): Int { return a * 2 } // double(2) == 4
- 引数は
val
なので(?)、再代入が不可
fun double(a: Int): Int { a = 0 // コンパイルエラー return a * 2 }
以下の書き方も可能です。
fun double(a: Int): Int = a * 2
- 戻り値の型が定義されていない場合、
Unit
型になる - 戻り値がある場合、型推論が可能なら省略可能
fun double(a: Int) = a * 2 // 戻り値の型は Int fun double(a: Int) = a * 2.0 // 戻り値の型は Double
- デフォルト値が書ける
fun double(a: Int = 0) = a * 2 // double() == 0
- 引数名を指定すると順不同で書ける
fun multiple(a: Int, b: Int) = a * b val c = multiple(b = 2, a = 4) // c == 8
- 型パラメータを使える
fun<T> toString(a: T): String = "$a"
ラムダ式
val a = {a: Int -> a * 2} println(a(2)) // 4
次のようにも書けます。
val a : (Int) -> Int = {a -> a * 2}
- デフォルト引数は使えない(?)
- ラムダ式をその場で実行できる
- 引数なしの場合、
->
の左側は何も書かない
println({ -> "Hello World!"}()) // Hello World!
高階関数
引数と戻り値の型に関数が指定できます。
fun execute(a: (Int)->Int): Int { return a(4) } val func = {a: Int -> a * 2} println(execute(func)) // 8
fun execute(a: Int): (Int) -> Int { return {a: Int -> a * 4} } println(execute(2)(3))
上記の例はあまり意味がありませんが、例えばロック処理を行うようなときに使えるようです。
クラス
class MyClass {} class MyClass // 同じ意味
val c = MyClass()
- 明示的なコンストラクタの定義
class MyClass(v: Int) {}
上記の場合、v
は MyClass
が持つプロパティにはなりません(コンストラクタ内でしか使えない)。
class MyClass(v: Int) { val value = v } // v は、メンバの初期化にしか使えない
val
,var
をつけるとプロパティを定義できる
class MyClass(val value: Int) { fun printValue() = println(value) }
init
でイニシャライザを作れる
class MyClass(var value: Int) { init { value = 0 } fun printValue() = println(value) } // コンストラクタで数値を入れても init で初期化される
class MyClass() { constructor(v: Int) : this() { print("Secondary") } } // MyClass(10) のようにするとセカンダリが呼ばれる
- セカンダリではプロパティを定義できない
アノテーションや可視性修飾子をつける場合、
constructor
キーワードをつける(?)- 可視性はなくても付けられる(?)
メソッドは、クラス内部で関数のように定義する
class MyClass(val value: Int) { fun printValue() = println(value) } // MyClass().printValue()
プロパティ
val
で定義すると読み取り専用になる(getter)var
で定義すると読み取り書き込み可能になる(getter, setter)
次のように呼び出します。
class MyClass(v: Int = 10) { val value: Int = v } // MyClass().value で呼び出せる
get
,set
は自分で作れる
class MyClass(v: Int = 10) { var value: Int get() { println("Called GetValue") return 100 } set(v: Int) { println("No Set") } }
get
,set
内でそのプロパティにアクセスすると無限ループするので注意- プロパティにアクセスしたい場合、(罰金)バッキングフィールド
field
を使う get
のアクセス修飾子は、プロパティと同じにしないといけないset
のアクセス修飾子は、異なる修飾子を指定できる
class MyClass(n: String = "") { private var name = n get() { return field } private set(value) { field = value } }
可視性修飾子
public
- デフォルト
- どこからでもアクセス可能
internal
protected
- 同一クラス内とサブクラス内からアクセス可能
private
- 同一クラスのみアクセス可能
オブジェクト(詳細は割愛)
class
ではなく、object
キーワードを使う。- シングルトンになる
コンパニオンオブジェクト(詳細は割愛)
- Kotlin は static なメンバを定義できない
- コンパニオンオブジェクトはその代わり
データクラス(詳細は割愛)
- データを保持するためだけのクラス
継承
- クラスはデフォルトでは継承できない
open
修飾子をつけると継承できるようになる
open class MyClass() class ExMyClass(): MyClass()
- 多重継承はできない
- オーバライドする場合、元のメソッドをオーバライド可能にする必要がある(
open
修飾子をつける) - オーバライドする側は、
override
をつける
open class MyClass() { open fun print() = println("MyClass") } class ExMyClass(): MyClass() { override fun print() = println("ExMyClass") }
インタフェース
interface
キーワードを使う
interface MyInterface { val value: Int fun print() = println("MyInterface") } // プロパティも定義できる open class MyClass(): MyInterface { override var value = 10 override fun print() = println("MyClass") }
- プロパティも定義できるが、継承先で必ず初期化しないといけない
- インタフェースをインタフェースに継承できる
interface ExMyInterface : MyInterface { override fun print() = println("ExMyInterface") }
object:
式で匿名クラスを作れる
interface MyInterface { val value: Int fun print() = println("MyInterface") fun printValue() = println(value) } interface ExMyInterface : MyInterface { override fun print() = println("ExMyInterface") } object: ExMyInterface{ override val value = 10 }.print() // ExMyInterface が出力される
パッケージ(詳細は割愛)
- Java と同じ機能
package mypackage.myclass class MyClass
import
でアクセスできるようになる
アクセス制限
public
- どこからでもアクセス可能
- デフォルト
internal
private
- 同一ファイル内のみ可能