/var/log/messages

debugging with sixth sense

Kotolin メモ

ちょっと弄って時間が経つとすべて cache から落ちているので控えを取ってみます。自分メモです。

確認させて頂いてるのは

です。

代表的な機能

NULL 安全

NPE を抑える記述が可能とのこと。

拡張関数

クラス定義の外でメソド追加が可能とのこと。

1
fun Int.odd() = this % 2 != 0

手続き定義の書き方忘れてるな。あと最近 Python 弄る機会がありましてそこともごっちゃになっているxD

関数リテラル

これ、手続きオブジェクトのことかな。lambda が使える、と。

1
2
3
4
5
6
  val sayHello = {
    (name : String) ->
    println("Hello, $name")
  }    

  sayHello("Taro")

S 式で書けるようにできないかなぁ (を

クラス

Employee というクラス定義が例示されている。

1
2
3
4
5
6
7
8
9
class Employee(val name : String) {
    
    var birthday : #(Int, Int, Int)? = null
    private set

    fun setBirthday(val year : Int, val month : Int, val day : Int) {
      birthday = #(year, month, day)
    }
}

birthday の型はリストになるのかどうか。

等価

参照等価、構造等価、という概念。== という演算子が無いのか。あ、違うや。== では参照等価を調べることができない模様。identityEquals というインラインな手続きがあると書いてますね。あと、インライン関数とか中置呼び出しとかって何だろ。

以下なコードが例示されてます。中置呼び出しの例にもなっている模様。

1
2
3
4
5
6
7
fun main(args : Array<String>) {
    val a = java.lang.Integer(500)
    val b = java.lang.Integer(500)

    println(a == b)             // true
    println(a identityEquals b) // false
}

キャスト

型チェックした後はキャスト不要らしい。smart cast か。あと、cast は as という演算子を使う模様。

手続きの定義

簡単な例として以下が記載されてます。

1
2
3
fun next(n : Int) : Int {
    return n + 1
}

六つの特徴がある、とのこと。

  • トップレベルでの手続き定義
  • fun キーワードによる手続き定義
  • 型宣言の位置
  • 変数の型宣言は不要
  • val とか var というキーワード
  • 文末を明示しなくてよい (; が不要)

以下な宣言が可能とのこと。

1
fun next(n : Int) = n + 1

一つの式のみの場合、この書き方ができる模様。

ローカル関数

手続きの中で定義された手続きをこう呼ぶ模様。Scheme とかと同じで手続きが第一級オブジェクトなのでできるワザ。

関数リテラル

Kotlin では関数と関数リテラルは異なるものですという記述があるな。関数リテラル、が lambda で定義できる手続きオブジェクト、って思っててよいかな。

例示されてるソレは one という定数を定義しています。

1
2
3
4
  val one : Int = {
    (n : Int) : Int -> 
    n + 1
  }(0)

Scheme で書くと以下? (one の定義は略)

1
  ((lambda (n) n + 1) 0)  

絶対こっちのが簡単だと思うんだけどなぁ。

  • 関数リテラルはブラケット ({}) で囲まれる
  • 最後に書かれた文が表す値が戻される
  • 仮引数、戻り値の型を宣言する場合、本文との間に –> を書く
  • 手続きの型は略せる

関数と関数リテラルの違い

普通に宣言された関数は第一級オブジェクトではない、とあります。あ、関数として定義されたソレを手続きオブジェクトとして関数に渡したりすると叱られるのか。

そして、手続きオブジェクトはオーバーロードできない、とかありますね。当り前なのかどうか。

クロージャ

以下が例示されています。いいですね。

1
2
3
4
5
6
7
8
9
10
fun main(args : Array<String>) {
  var n = 0
  
  fun next() {
    n++
  }
  
  next()
  println(n)
}

中置呼び出し

Infix call というらしい。以下の条件を満たせば良い模様。

  • メンバ関数 (または拡張関数)
  • 引数一つ

ジェネリック関数

定義が可能な模様。以下が例示。

1
2
3
fun head<T>(array : Array<T>) : T {
    returnn array[0]
}

あるいは拡張関数として書くと以下とのこと。

1
fun <T> Array<T>.head() = this[0]

デフォルト引数と名前付き引数

Default argument によってオーバーロードを減らすことができる、のか。Named argument ってのもあるのね。例の引用は略。

演算子オーバーロード

簡単に実現可能とのこと。ここに Kotlin が提供する演算子の一覧がある模様。

if

式になってて値を戻す模様。

when

switch はないけれど、とのこと。これも値を戻すのか。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fun main(args : Array<String>) {
  val a = 7
  
  val b = when(a) {
    1 -> "1st"
    2 -> "2nd"
    3 -> "3rd"
    seven() -> "lucky seven!"
    4, 5, 6, 7, 8, 9 -> "${a}th"
    else -> "unknown"
  }
  
  println(b) // "lucky seven!"
}

fun seven() = 7

これ、最初意味分かりませんでした。よくよく見てみるに seven() の呼び出しが when な文の中にあるのを発見した次第ス。

そして FizzBuzz の例が出てます。

1
2
3
4
5
6
when {
    a.isFizz() && a.isBuzz() -> "fizzbuzz"
    a.isFizz() -> "fizz"
    a.isBuzz() -> "buzz"
    else -> a
}

これはこれは。また、when はパターンマチングをサポートとありますね。

for ループ

以下な書き方ができるとのこと。

1
2
3
  for(val arg in args) {
    println(arg)
  }
  • arg は val または var を指定 (デフォルトは val)
  • arg はイテレータを提供するオブジェクトでなければならない
  • 関数 iterator() を持ってるオブジェクトはイテレータを提供する
  • 関数 next() を持ってて Boolean 型の関数 next() またはプロパティ next を持っているオブジェクトはイテレータを提供する

ラベル付き return

break も continue もラベル指定の jump が可能らしい。

クラスの定義

簡単な例として以下が例示されています。

1
2
3
4
class Person(name : String, age : Int) {
  val name = name
  val age = age
}

これ、こう書けるみたいです。

1
class Person(val name : String, val age : Int)

匿名イニシャライザ、というものもある模様。

1
2
3
4
5
6
7
class Person(firstName : String, lastName : String) {
  val name : String
  
  {
    name = firstName + " " + lastName
  }
}

属性 name にコンストラクタの引数な文字列を空白区切で連結させて、なのか。

継承

以下な記述。open というアノテーションで継承を許可するとのこと。

1
2
3
4
open class Foo(val a : Int)

// クラス Fooを継承
class Bar(a : Int) : Foo(a)

基本的には継承不可、なのか。< Effective Java

override

厳しいルールがあるようで。

  • メンバ関数はデフォルト override 不可
  • 許可するには open アノテーション付けて定義
  • override 時には override アノテーションを付ける

あるいは

  • open 指定してないクラスのメンバ関数には open 付けれない
  • override した関数に open アノテーションは付けれない (スデに open)
  • override した関数の override を許可しない場合、final アノテーションを付ける

プロパティ

フィールドではなく、プロパティです、とのことですがどうも以降を見るに

  • プロパティの宣言でフィールドと二つのアクセサを内部的に作成

とありますね。

アクセサ

自分で定義する場合の書き方、が例示 (?) されています。

1
2
3
4
5
6
var プロパティ名 : 型 = 初期値
 get() {
  return 返す値
 }
 set(value) {
 }

値を持たないプロパティ、という面白い例が載っていますが略。

プロパティの override

可能とのこと。今回はここまでで残りは別途。つうかこれ、勉強会したいな。

Comments