Androidなんも分からん (Kotlin編2)

初めに

前回の続き


真面目にやる

続き


Functions and Lambdas

function分からんとなんも分からんよな。

Functions

あまり新しいことはなかった。ほぼScalaと同じ感じで定義できる。

Swiftのような、というよりはScalaに近いnamed argumentsの仕組みがある。

varargを引数につけると、いわゆる可変長引数にすることができる。arrayの前にspread operatorと呼ばれる*を付与することで、arrayの各要素を展開することができる。

infixをつけると中置記法を使える。ただし、1引数のmember functionもしくはextension functionのみで、引数はデフォルト値ももたず、varargであってもダメ。

また、再帰呼び出しを行う関数に対して、tailrecをつけると、末尾再帰化を試みる。

Lambdas

function typeをinterfaceとして実装したclassを定義できる(マジか)。

また、function typeの(A, B) -> CA.(B) -> Cは交換可能らしい(マジか)。

lambda式の定義は次のようにしてできる。return typeがUnitでない場合、一番最後に評価された式がそのlambdaからのreturn valueになる。

高階関数において、関数を引数リストの最後にとる場合、Swiftなどでよくある形でlambdaを渡すことができる。

また、コンパイラがlambdaに渡される引数の型や返り値の型を推論できる場合、->などは省略でき、代わりにitという変数を引数値として使うことができる。Swiftみたく$0とかではなくて名前がついちゃっててちょっとキモいかも。

anonymous functionというものもある。

こいつの利点は、ラベル無しでただreturnを書いたときに、そのfunからreturnする点。つまり、lambdaのときのように、内包しているfunctionそのものをreturnするという動作にならない。

Inline Functions

inline classと同様に、inline functionという機能もある。inlineが付与されたfunctionは、呼び出した箇所でコンパイラによってコード展開され、function objectを生成するといったoverheadを少なくできる。

inline functionにおいて、型パラメータにreifiedを付与すると、function内で、渡された型情報を知ることができる(type erasureされない)。


Multiplatform Programming

ほぇ〜と思った点だけ抜粋。

expectというkeywordを付与すると、各platform上で実装されることを想定して、宣言時点では実装を与えなくてもよいようにできる。

これを実装するJVM上のコードは次のようになる。actualがきも。


Others

この辺くらいまでやって終わりにしよ。

Destructuring Declarations

Destructuring Declarationってなんのこっちゃって思ったけど、コードみて完全に理解した。これそういう名前なんね。

実際には、コンパイラによって次のコードに変換されるらしい

なるほどね。mapのkey-value pairの宣言もできるし、for-loop内でも使える。

Collections

Kotlinでは、明確にmutableとimmutableなcollectionを区別する。次のコードが好例。

Ranges

range expressionのfunction形式がrangeToとあるように、..は右側の値も含む

stepdownToもあるし、なんならuntilもある(あるんかい)。

閉区間と半開区間周りは言語によってはややこしいから、Swiftみたく.....<みたいな素直なのが良いよね。。

Type Checks and Casts

ランタイムにおける型チェックにisおよび!isが使える

そして噂のSmart Cast。これほんと賢いでしょ。。。

asを用いたcastはexceptionを投げる可能性があるため、Unsafe castと呼ばれている。

また、as?を用いたcastは、exceptionを投げない代わりに結果がnullableなので、Safe (nullable) castと呼ばれている。

Genericなclassの型情報はコンパイル時に消去されるため、型パラメータを含めたisのチェックは行えない。代わりに*を型パラメータの位置に書くことで、Genericsを無視した単なるclassとしてのisチェックは行える。

なお、functionの引数などで型情報を明記している場合は、isチェック時に<*>を省略できる。

This expressions

receiverとしてthis keywordを使用できる。inner class内やreceiverが指定されたfunction内など、どのreceiverを指すのか不明になる場合は、this@Aのようにラベルで明記してあげる。Kotlinめっちゃラベル使うやん。

Equality

Structural equalityのチェックには==を使用し、Referential equalityのチェックには===を使用する。

Operator overloading

operatorのoverloadもできる。その際、どのoperatorがどのmethod名に変換されるのかは予め決められている。次のコードはunaryMinusの例。すなわち単項演算子であるをoverloadしている。

Null Safety

多くのモダンな言語と同様に、Kotlinにおいてもnon-nullとnullableの区別がある。

もちろん、bob?.department?.head?.nameのようなsafe callのchainもできる。

Elvis operatorと呼ばれる演算子がある。Swiftでいう?? (nil合体演算子)。

not-null assertion operatorもある。!!と書く(Swiftよりヤバイ度合いが伝わる)。nullの場合はexceptionが投げられる。

Exceptions

exceptionを投げる可能性のあるコードはtry expressionで包む。expressionであるため、2つめのような記述もできる(エモい)。

throwもexpressionであるため、Elvis expressionとともに使うことができる。

また、throw expressionはNothingという特別な型となっている。

このNothingという型は、throwを伴わないexpressionにおいても、ときおり目にすることがある。それはnullだけを取りうる変数の型として、である。(なるほど)

Annotations

annotationとは、コードに対してmetadataを付与することのできる機能である。annotationはannotation keywordと共にclassを宣言することで作成できる。

Reflection

最も基礎的なreflectionは、ランタイムにclassの型情報を得る機能である。

また、:: operatorを用いることで、高階関数に対して関数の型を渡すことができる。

Type-Safe Builders

長いので詳細は省く。

Kotlinでは、HTML.() -> Unitのように、function typeにrecieverのtypeも指定できるため、エモい感じでDSLを作ることができる。これ面白そう。遊んでみよ。

Type Aliases

typealiasは次のようにして宣言できる。


終わりに

Kotlin完全に理解しました。嘘です。

とりあえず、概要は把握できたと思う。ざっと見た上でKotlinの際立ってる点をあげると、

  • Smart Castが激エモい
  • Enum Class/Data Class/Sealed Classというように、基本的にclassがベースとなっている
  • 構文レベルでDelegation Pattern推している
  • function typeでreceiverの型も指定できる(表現の幅が広がり、DSLのようなものが容易に作れる)

といった感じ。だと思う。

なお、この記事におけるコード例は、そのほとんどがKotlinの公式からコピペしたものです。

次からはぼちぼちAndroid SDKを触り始めよう。

kage

A student at Tokyo Institute of Technology. Programmer.

あわせて読みたい

コメントを残す

%d人のブロガーが「いいね」をつけました。