何らかの言語修得者用 差分で覚えるKotlin その一

# 00. 目次

1. [何らかの言語修得者用 差分で覚えるKotlin その一](https://qiita.com/makky775/items/fa6d0a47f18a68e66913 "その一")  
現在のページ。変数, 分岐, ループ, 関数等のまとめ。オブジェクト指向の知識不要
2. [何らかの言語修得者用 差分で覚えるKotlin その二](https://qiita.com/makky775/items/848c54f3729386ea9dbb "その二")  
クラスとインターフェースのまとめ。オブジェクト指向の知識が必要
3. [何らかの言語修得者用 差分で覚えるKotlin その三](https://qiita.com/makky775/items/03ad228c9a5d8d885ffd "その三")  
ジェネリクスと、配列やコレクションのまとめ。オブジェクト指向の知識が必要

<br/>
# 01. はじめに

+ 既に何らかのプログラミング言語を一つ以上修得した方が、ざっくりとKotlinを知るためのまとめです
+ 要点や他言語との差分に絞って記載することで修得時間の短縮を狙っています
+ 記載されていない部分は他言語と大体同じとお考え下さい  
  例: コメントは// か/* ～ */、スペース,記号,アルファベット,数字は半角等
+ 修得言語はC,C++,C#,Java,JavaScript等を想定しています
+ このページではオブジェクト指向を扱っていませんので、関数, 順次処理, 分岐, ループ等をご存じであれば大丈夫です
+ 筆者はC,C++,Java(1.2とかいう古典),VB,JS等を修得済、Kotlinを現在勉強中。間違い等あればご指摘頂けると幸いです

# 02. 基本のキ

+ 関数のはじまりは`fun`と書く
+ 関数は`{}`で囲う
+ 最初にコールされる関数は main関数
+ 行の終端に`;`は不要
+ 一行に複数の処理を記述する場合は、各処理を`;`で区切る
+ 他ファイルに記述したクラスを利用する場合はパッケージをインポートする(Javaと同じ)

```Kotlin
fun main (args: Array<String>){
	println("Hello, world!")  // printlnはコンソールに1行出力する
	println("Hello, world!"); println("Goodbye, world")
}
```

<br/ >
# 03. 変数とデータ型

## 定数
所謂constやfinal、一度値を設定すると変更できない変数を指す
`val 任意の変数名: 変数の型 = 値`

```Kotlin
val message:  String = "Hello, World!"
// ": 変数の型"は省略可
val message2 = "Hello, World!"
```


## 変数
`var 任意の変数名: 変数の型 = 値`  

```Kotlin
var message:  String = "Hello, World!"
// ": 変数の型"は省略可
var message2 = "Hello, World!"
```

## null許容型の変数
変数に`null`が入る可能性がある場合は、変数の型の後ろに`?`をつける
`var 任意の変数名: 変数の型? = 値`  

```Kotlin
var message: String? = null
```

null許容型変数は取扱いに気をつけないと、エラーや例外が発生しやすい

```Kotlin
// これは問題なし
var message: String = ""
println("文字列長：" + message.length)  // String.length = Stringの文字列長

// これはコンパイル前にエラーになる
var message_null: String? = null
println("文字列長：" + message_null.lengh)  // null許容型変数は、そのままでは文字列長が取得できない

/*
* 解決方法
*/
// 1.セーフコール
var message_null: String? = null
println("文字列長：" + message_null?.length)  // message_nullがnullの場合、lengthはnullとなる

// 2.事前nullチェック
var message_null: String? = null
if(message_null != null)
    println("文字列長：" + message_null.length)  // 事前にnullチェックしているのでコンパイルが通る

// 3.エルビス演算子を使う
//   式1 ?: 式2 (式1がnullの場合、式2を評価する)
var message_null: String? = null
// 四則演算はエルビス演算子より優先されるため、()で囲う
println("文字列長：" + (message_null?.length ?: 0))  // message_nullがnullの場合、0を返却する
```


## 変数の型一覧
| 変数の型(クラス)   | 範囲              | 
|:-----------------|:------------------|
| Byte             |         -127～127 |
| Short		   |     -32767～32767 |
| Int		   |  長いので省略 32bit|
| Long		   |  長いので省略 64bit|
| Float		   |    浮動小数点 32bit|
| Double           |    浮動小数点 64bit|
| Char		   | 文字              |
| String	   | 文字列            |
| Boolean	   | true or false    |
| ***Range         | 範囲型(別項で説明) |

+ Long型を明示的に定義する場合は、末尾にLをつける  
`val a: Long = 10000000000L`
+ Float型を明示的に定義する場合は、末尾にfをつける  
`val a: Float = 1.123456f`
+ 数字を読みやすくするために、数字の間に"_"を挟むことが出来る  
val a: Int = 10&#095;000&#095;000     // 10,000,000

## 範囲型変数

数値や文字を範囲で記憶する変数が存在する

```Kotlin
val a: IntRange = 0..6      // 0から6の間
val b:CharRange = 'A'..'E'  // AからEの間
```

+ if文で変数値の範囲を調べる時にとても便利  
`if(変数 in 値a..値b)`
+ 範囲外かどうかを調べる時には `!in` と書く


```Kotlin
	// 普通に書いた場合
	val age: Int = 17
	if(0<=age && age<=19){
		println("under age")
	}

	// 範囲型を使った場合
	val age: Int = 17
	if(age in 0..19){
		println("under age")
	}
```

## 型推論と型変換
変数や関数の戻り値等は型を定義しなくても動作する(**型推論**の機能)

```Kotlin
val a: String = "Hello, World!"
val b = "Hello, World!"
```

しかし特定の型を別の型に変換する時は、明示的に型変換関数を呼び出す必要がある

```Kotlin
val a: Int = 100
val b: Double = a  // 型変換していないのでエラー

val a: Int = 100
val b: Double = a.toDouble()  // これはOK
// 他にも色々あります. toByte, toInt, toChar, toString… 
```

文字列を数値に変換する場合は、例外の発生に注意

```Kotlin
val a: String = "Hello, World!"
val b: Int = a.toInt()   // 数値に変換できないため、例外 NumberFormatException が発生

// toIntOrNullを使用すると例外が発生しません
val a: String = "Hello, World!"
val b: Int? = a.toIntOrNull()   // 例外は発生しない b=nullとなる
```


<br/ >
# 04. 文字と文字列
## 文字と文字列の基本

+ 1文字はシングルクォートで囲む
+ 文字列はダブルクォートで囲む
+ ダブルクォート*3で囲むと、コードそのままの文字列を扱える

```Kotlin
// .trimMargin()で、"|"より左の空白文字を削除できる
val text: String = """dog,
                   |cat,
                   mouse""" .trimMargin()

出力結果：
dog,
cat,
                       mouse
```

+ 文字列内に変数を挿入できる  
`${変数名}`

```Kotlin
val student: String = "Mary"
// {}は省略可
val list: String = "junior high school student, ${student}"
```

## 文字列の結合
文字列の結合は `"+"` を使う

```Kotlin
val a: String  = "Hello, "
val b: String  = "World! "
println(a+b)  // Hello, World! と出力
```

## 文字列の比較(調査中)
*※これ以降少しクラスの話が出ますが、クラスをご存じない方は読み飛ばしても問題ありません*

+ 完全一致は`==`か、正規表現用の**RegEx**クラスの`matches`メソッド
+ 部分一致や前方一致等は、**String**クラスか**RegEx**クラスのメソッドを使用する

| 比較方法    | メソッド名      | 
|:-----------|:---------------|
| 部分一致    |RegEx.containsMatchIn |
| 前方一致    |startsWith      |
| 後方一致    |endsWith        |

## 文字列の置換(調査中)
+ **RegEx**クラスの`replace`メソッド
+ 正規表現が使える

## 文字列の分割(調査中)
+ **String**クラスか**RegEx**クラスの`split`メソッド


<br/ >
# 05. 演算子
## 算術演算子(大体他言語と同じ)
| 種類       | 記号        | 
|:-----------|:----------:|
| 加算       |+           |
| 減算       |-           |
| 乗算       |*           |
| 除算       |/           |
| 余り       |%           |

+ 演算子の優先順位は、数学と同じく除算乗算優先
+ エルビス演算子(?:)は四則演算より後回しになる
+ インクリメント(++)、デクリメント(--)も使える
+ 複合代入演算子(`-=` 他)も使える

```Kotlin  
	a = a+1
	a += 1	// 結果は同じ
```

## 比較演算子
| 種類       | 記号        | 
|:-----------|:----------:|
| 等しい     |==           |
| 等しくない |!=           |
| 大きい、小さい | <, >    |
| 以上、以下  |>=, <=      |
| 参照が等しい ※|===         |
| 参照が等しくない ※|!==     |
※ 参照の比較は、Cで言うところのアドレスの比較


## 論理演算子(大体他言語と同じ)

| 種類       | 記号       | 
|:----------|:----------:|
| AND       |&&          |
| OR        |&#124;&#124;|
| NOT       | !          |


<br/ >
# 06. 条件分岐
三項演算子は存在しない
~~`条件 ? 真 : 偽`~~ ←これは使えない

## if
`if(条件) ～ else if(条件) ～ else`

```Kotlin  
val age: Int = 17
if(age in 0..19){  // 範囲型変数の項を参照
	println("under age")
}
else{
	println("grownup")
}
```

## when
switch文に似ている
`when(変数) {条件1 -> 処理1; 条件2 -> 処理2; else -> 処理}`

```Kotlin 
val pet: String = "cat"
when(pet){
    "dog" -> println("bow wow")
    "cat" -> println("mew")
    "mouse" -> println("squeak")
     else  -> println("not found")
}
```

条件の変数を省略出来る

```Kotlin 
val pet: String = "cat"
// 上の例から変数petを省略
when{
    (pet == "dog") -> println("bow wow")
    (pet == "cat") -> println("mew")
    (pet == "mouse") -> println("squeak")
     else  -> println("not found")
}
```



if, when共に **分岐結果を戻り値として返す**ことが出来る

```Kotlin 
val pet: String = "cat"
val message: String = when(pet){
    "dog" -> "bow wow"
    "cat" -> "mew"
    "mouse" -> "squeak"
     else  -> "not found"
}
println(message)  // mewと出力
```

<br/ >
# 07. 繰り返し処理
## for
+ インデックスをインクリメントしてループするタイプのfor文は存在しない  
  ~~`for(i = 0; i< 10; i++)`~~ ←これは使えない
+ for-eachやforeach,for-in等と呼ばれるタイプのfor文を使用する  
  `for(変数 in 配列やコレクション)` ←これは使える
+ `continue` や `break`は使える

`for(変数 in 範囲) ～` の場合

```Kotlin
// 基本形 iが0～3までの間ループ
//      var i: Int とは書けない. i: Intなら書ける
for(i in 0..3){
    println("count:" + i) // 0,1,2,3を出力
}

// 応用 1ループ毎にiを+3
for(i in 1..9 step 3){
    println("count:" + i) // 1,4,7を出力
}

// 応用 降順ループ  
//     3 >= i => 1 の間ループ
for(i in 3 downTo 1){
    println("count:" + i) // 3,2,1を出力
}

// 応用 1ループ毎にiを-3
//     9 >= i => 2 の間ループ
for(i in 9 downTo 2 step 3){
    println("count:" + i) // 9,6,3を出力
}

```

`for(変数 in 値a until 値b) ～` の場合、**a <= i < b** の範囲をループする

```Kotlin
// 基本形 iが0～2までの間ループ
//     上の例と出力結果が異なることに注意
for(i in 0 until 3){
    println("count:" + i) // 0,1,2を出力
}

// 応用 1ループ毎にiを+3
for(i in 1 until 9 step 3){
    println("count:" + i) // 1,4,7を出力
}
```

## while, do while

+ `while(条件) ～` が基本
+ `while(true) ～` の無限ループも可. ループを抜ける時は`break`
+ `do ～ while(条件) ` も使える

```Kotlin
var i: Int = 0
while(i<3){
    println("count:" + i++) // 0,1,2を出力
}
```

<br/ >
# 08.関数
## 関数の宣言
+ `fun 関数名(引数名: 引数の型 [, 引数が複数ある場合は繰り返し]) :  戻り値の型`
+ 引数で`null`を渡す可能性がある場合は、引数の型の後ろに`?`をつける
+ 関数名は、慣習では関数名の先頭を小文字, 単語の先頭を大文字
+ 戻り値が無い場合は `Unit` と書くか、何も書かない
+ 戻り値がある場合でも型宣言を省略出来る(型推論の機能)

```Kotlin
/*   基本形
	fun 関数名(引数名: 引数の型 [, 引数が複数ある場合は繰り返し]) :  戻り値の型 {
	    ～ 処理 ～
	    return 戻り値
    }
*/
fun main() {
    println(getTotalAmount(0.1f,198,298))  // 546と出力
}

// 引数itemの合計に税率をかけて合計金額を返す
fun getTotalAmount(tax: Float, item1: Int, item2: Int) : Int {
	// Math.round は四捨五入処理
	return Math.round((item1+item2) * (1 + tax))
}
```

上の関数 をさらに省略して書くとこうなる

```Kotlin
/*   省略形
	fun 関数名(引数名: 引数の型 [, 引数が複数ある場合は繰り返し]) =   戻り値
*/
fun getTotalAmount(tax: Float, item1: Int, item2: Int) = Math.round((item1+item2) * (1 + tax))
```

可変長引数を使用する場合
`fun 関数名(vararg 引数名: 引数の型 ) : 戻り値の型`
※ 配列の詳細については別ページにまとめる予定です

```Kotlin
/*   可変長引数有り
	fun 関数名(vararg 引数名: 引数の型 ) : 戻り値の型
*/
fun getTotalAmount(tax: Float, vararg items: Int) : Int {
	var total: Int = 0
	for(i in items){	// itemsはInt型の配列
		total += i
	}
	return Math.round(total * (1 + tax))
}

fun main() {
    // 関数呼び出し側は、可変長引数にスプレッド演算子(*)をつける
    println(getTotalAmount(0.1f, *intArrayOf(198, 298, 398)))
}
```

名前付き引数とデフォルト引数も使用できる

```Kotlin
/*   
	名前付き引数を使ってgetTotalAmountを呼び出す
*/
fun main() {
    println(getTotalAmount(tax=0.1f,item2=198,item1=298))
}
fun getTotalAmount(tax: Float, item1: Int, item2: Int) : Int {
	// item1は298
	return Math.round((item1+item2) * (1 + tax))
}

/*   
	デフォルト引数を設定する
*/
// item1とitem2にデフォルト引数を設定
fun getTotalAmount(tax: Float , item1: Int = 0, item2: Int = 0) : Int {
	return Math.round((item1+item2) * (1 + tax))
}
```

## 関数と可視性修飾子
関数にも可視性修飾子をつけることが出来る
省略も可能
`可視性修飾子 fun 関数名(引数名: 引数の型 [, 引数が複数ある場合は繰り返し]) :  戻り値の型`

| 種類       | 可視性範囲           | 
|:----------|:--------------------|
| 省略(未指定)|どこからでもアクセス可能|
| public    |どこからでもアクセス可能|
| protected |関数では使えない(クラスはOK)|
| private   |同じファイル内からのみアクセス可能|
| internal  |モジュール内からのみアクセス可能|

## 関数のオブジェクト化
※ ラムダ式と一緒にまとめる予定