7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Kotlin】`..` ってなに?

Last updated at Posted at 2019-02-23

古典的な for 文

// Java
for (int i = 0; i <= 9; i++) {
    System.out.println(i);
}

は Kotlin では次のように書けます。

(0..9).forEach {
    println(it)
}

しかし、.. ってなんでしょうか。
0..9 の型はなんでしょうか。

..

..rangeTo 関数に変換される2項演算子です

演算子オーバーロード

Kotlin では演算子オーバーロードによって、演算子の処理を 被演算子の型ごとに 関数(メンバ関数もしくは拡張関数)として実装しています。1
関数名は演算子によって決まっています。(.. の場合は rangeTo です。)
被演算子(関数の引数。拡張関数の場合はレシーバーも含む)と演算結果(関数の返値)の型は任意(演算子の種類によって制限されることはない)のようです。

rangeTo

rangeTo 関数の実装は標準ライブラリーには次のものがあります。

引数 返値 APIドキュメント
Comparable<T> ClosedRange<Comparable<T>> kotlin.ranges
Double ClosedFloatingPointRange<Double> kotlin.ranges
Float ClosedFloatingPointRange<Float> kotlin.ranges
一方が Long、他方が Long / Int / Short / Byte LongRange Long / Int / Short / Byte
Int / Short / Byte IntRange Int / Short / Byte
Char CharRange Char
ULong ULongRange ULong
UInt UIntRange UInt
UShort UIntRange UShort

ここに現れる型をクラス図に表すと次のようになります。

引数:

image.png

PlantUML ```uml @startuml Comparable <|.. Double Comparable <|.. Float Comparable <|.. Long Comparable <|.. Int Comparable <|.. Short Comparable <|.. Byte Comparable <|.. Char Comparable <|.. ULong Comparable <|.. UInt Comparable <|.. UShort interface Comparable @enduml ```

返値:

image.png

PlantUML ```uml @startuml ClosedRange <|-- ClosedFloatingPointRange ClosedRange <|.. LongRange ClosedRange <|.. IntRange ClosedRange <|.. CharRange ClosedRange <|.. ULongRange ClosedRange <|.. UIntRange interface ClosedRange interface ClosedFloatingPointRange @enduml ```

つまり標準ライブラリーが用意している rangeTo は2つの Comparable から ClosedRange を生成する関数ということになります。

ClosedRange

ClosedRange インターフェイスは閉じた範囲を表します。
プロパティとして範囲の始点終点のみを持ち、
独自のメンバ関数(拡張関数でない)としては指定された値が範囲に含まれるかどうか範囲が空かどうかのみを持ちます。
実は Comparable インターフェイスを実装しているため、上記に加えて同型オブジェクトとの大小比較を行うメンバ関数も持っていますが、
これ以外のプロパティ・メンバ関数は持っていません。

おや、これでは forEach 拡張関数で反復処理するための情報が足りませんね。
ということはこのインターフェイスを継承・実装している型に反復処理のためのプロパティやメンバ関数があるということになります。
実際、ClosedRangeClosedFloatingPointRange に対しては forEach は使えません。

(0.0..9.0) // ClosedFloatingPointRange を返す。
    .forEach { // コンパイルエラー!
        println(it)
    }

Iterable

rangeTo 関数の返値の型を先ほどクラス図にしましたが、そのときは未出の型を省いていました。
ここで完全版を見てみましょう。

image.png

PlantUML ```uml @startuml Comparable <|-- ClosedRange ClosedRange <|-- ClosedFloatingPointRange ClosedRange <|.. LongRange ClosedRange <|.. IntRange ClosedRange <|.. CharRange ClosedRange <|.. ULongRange ClosedRange <|.. UIntRange LongProgression <|-- LongRange IntProgression <|-- IntRange CharProgression <|-- CharRange ULongProgression <|-- ULongRange UIntProgression <|-- UIntRange Iterable <|.. LongProgression Iterable <|.. IntProgression Iterable <|.. CharProgression Iterable <|.. ULongProgression Iterable <|.. UIntProgression interface Iterable interface Comparable interface ClosedRange interface ClosedFloatingPointRange @enduml ```

Iterable が出てきましたね!
Iterable には forEach の拡張関数があるので、Iterable を実装している IntRange などの型には forEach を使えるのです。

まとめ

  • .. は2項演算子で、rangeTo 関数に変換される。
  • 0..90.rangeTo(9) に変換され、IntRange 型オブジェクトを返す。
  • .. 演算の被演算子の型によっては forEach 関数を使えない。

参考

Ranges - Kotlin Programming Language
Operator overloading - Kotlin Programming Language

  1. + 演算子による整数同士の加算などでもそうです。→plus - Kotlin Programming Language

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?