見出し画像

[macOS][Kotlin]null安全

Cocoa + Objective-C では、nilは許容されるものでnilに対してメソッド呼び出しを行なってもアボートしないが、Javaだとnullアクセスは例外が投げられてしまう。そのような考えの違いが、null安全についても、SwiftとKotlinで差となっているのかな?

JavaではC言語の基本的データ型に相当するのが基本型(プリミティブ型)で、C言語の構造体に相当するクラスはC言語のポインタ型に相当する参照型(リファレンス型)となる。そして、C言語と同様に値渡しのみとなる。

Kotlinでは全ての型はオブジェクトで、それは参照型(リファレンス型)となる。参照型だとJavaではnullを代入できるが、Kotlinではnullが代入できるnull許容(nullable)と、null非許容(non-nullable)がある。

null許容は型名に?を付ける。

var a: String? = null

null非許容は型名に?を付けない。以下はコンパイルでエラーとなる。


var a: String = null

null許容の変数は、nullの可能性があるので、そのまま利用するとコンパイルでエラーとなる。

fun main(args: Array<String>) {
   var s: String? = "demo"
   var n = s.length
   print(n)
}
Error:(3, 14) Kotlin: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?

セーフコール演算子(?.)を使うと、nullでない場合は評価され、nullだと回避される。

var s: String? = "demo"
var n = s?.length
print(n)

セーフコール演算子を使う場合は、nullでないことの確認を行うことになると思うが、素直に書くと以下のようになる。

var s: String? = "demo"
if (s != null) {
   var n = s?.length
   print(n)
}

もっとスマートに書くために、セーフコール演算子と一緒に使えるlet関数が用意されている。

var s: String? = null
s?.let {
   var n = it.length
   print(n)
}

デバッグなので強制的にnullでないものとして使うための非null表明演算子(non-null assertion operator)、または、二重感嘆符演算子(double-bang operator)と呼ばれる演算子(!!.)がある。

var s: String? = "demo"
var n = s!!.length
print(n)

別のnullチェックのやり方として、null合体演算子(null coalescing operator)、または、エルヴィス演算子と呼ばれる演算子(?:)がある。

var s: String? = null
var t = s ?: ""
var n = t!!.length
print(n)

let関数とnull合体演算子を組み合わせると、以下のように書ける。

var s: String? = null
s?.let {
   var n = it.length
   print(n)
} ?: print("s is null.")

Kotlinで特徴的なのは、文法的にnullチェックされているのが分かっている場合は、コンパイラをnullチェック済みとするところだ。

var s: String? = "demo"
if (s == null) {
   print("s is null")
   return
}
var n = s.length
print(n)

これは開発環境を提供している会社が作ったプログラミング言語だからなせる技か。Kotlinには似たような割り切りを感じる部分が他にもある。機会があれば後で取りあげたい。

【関連情報】
- Cocoa.swift
- Cocoa勉強会 関東
- Cocoa練習帳

この記事が気に入ったらサポートをしてみませんか?