LoginSignup
17
15

More than 3 years have passed since last update.

SwiftとKotlinの構文比較 (1) 〜シンプルな値、制御フロー、関数とクロージャー

Last updated at Posted at 2017-11-19

はじめに

最近のKotlinの動向は熱いですよね。
特にAndroidの公式な開発言語になったことと、Spring 5が公式サポートしたことはインパクトがあり、私もKotlinの学習を始めました。

この記事は私のような「Kotlinが気になっているSwiftプログラマー」向けです。
Apple公式のSwiftチュートリアル A Swift Tour を、Kotlinで書き替えてみました。

長くなったので記事を分けました。

第一回(この記事)
 ・シンプルな値
 ・制御フロー
 ・関数とクロージャー

第二回
 ・クラス
 ・列挙体
 ・構造体
 ・プロトコル(インターフェイス)
 ・拡張

前提バージョン

  • Swift 4
  • Kotlin 1.1

Hello, World!

Swift
print("Hello, world!")
Kotlin
fun main(args: Array<String>) {
    println("Hello, world!")
}

どちらも;は不要です。私は素敵だと思います。:relaxed:

シンプルな値

変数と定数

Swift
var myVariable = 42
myVariable = 50
let myConstant = 42
Kotlin
var myVariable = 42
myVariable = 50
val myConstant = 42

定数(再代入できない変数)は、Kotlinはval

型推論と型宣言

Swift
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70
Kotlin
val implicitInteger = 70
val implicitDouble = 70.0
val explicitDouble: Double = 70.0

近年開発された言語では、型宣言は後置が主流みたいですね。

Kotlinのデータ型についてはこちら。
Kotlin Reference -Basic-Types

明示的な型変換

Swift
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
Kotlin
val label = "The width is "
val width = 94
val widthLabel = label + width.toString()

Kotlinは、val widthLabel = label + widthでもOKです。
Swiftとの比較のため、あえて上のように書きました。

文字列への変数の埋め込み

Swift
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
Kotlin
val apples = 3
val oranges = 5
val appleSummary = "I have ${apples} apples."
val fruitSummary = "I have ${apples + oranges} pieces of fruit."

複数の行を使用する文字列

Swift
let quotation = """
I said "I have \(apples) apples."
And then I said "I have \(apples + oranges) pieces of fruit."
"""
Kotlin
val quotation = """
I said "I have ${apples} apples."
And then I said "I have ${apples + oranges} pieces of fruit."
"""

コレクション

Swift
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"
print(shoppingList) // ["catfish", "bottle of water", "tulips", "blue paint"]

var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"
print(occupations) // ["Malcolm": "Captain", "Jayne": "Public Relations", "Kaylee": "Mechanic"]
Kotlin
var shoppingList = mutableListOf("catfish", "water", "tulips", "blue paint")
shoppingList.set(1, "bottle of water")
println(shoppingList)  // [catfish, bottle of water, tulips, blue paint]

var occupations = mutableMapOf(
    "Malcolm" to "Captain",
    "Kaylee" to "Mechanic"
)
occupations.set("Jayne", "Public Relations")
println(occupations) // {Malcolm=Captain", Kaylee=Mechanic, Jayne=Public Relations}

Kotlinのコレクションは仕様的にJVMの制約を引きずっているようですし、JavaのコレクションAPIも使えるので、使いこなすにはそれなりの学習が必要そうです。:sweat_smile:
Kotlin Reference -Collections
Kotlinコレクション入門

制御フロー

forループとif文

Swift
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
    if score > 50 {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
print(teamScore) // 11
Kotlin
val individualScores = listOf(75, 43, 103, 87, 12)
var teamScore = 0
for (score in individualScores) {
    if (score > 50) {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
println(teamScore) // 11

Kotlinの条件式は( )が必須です。
SwiftもKotlinもCスタイルのループfor (Int i = 0; i < n; i++)は廃止されています。
Swiftはi++++ii----iの演算子は廃止されていますが、Kotlinでは使えます。

while文

Swift
var n = 2
while n < 100 {
    n *= 2
}
print(n) // 128

var m = 2
repeat {
    m *= 2
} while m < 100
print(m) // 128
Kotlin
var n = 2
while (n < 100) {
    n *= 2
}
println(n) // 128

var m = 2
do {
    m *= 2
} while (m < 100)
println(m) // 128

Null Safety

Swift
var optionalString: String? = "Hello"
print(optionalString == nil) // false

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
    println(greeting) // Hello, John Appleseed
}
Kotlin
var optionalString: String? = "Hello"
println(optionalString == null) // false

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
optionalName?.let {
    val name = it
    greeting = "Hello, ${name}"
    print(greeting) // Hello, John Appleseed
}

SwiftのOptionalはKotlinではNullableと呼びます。
Kotlinのitはなかなかイケてると思いました。

Swift
let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"
print(informalGreeting) // Hi John Appleseed
Kotlin
val nickName: String? = null
val fullName: String = "John Appleseed"
val informalGreeting = "Hi ${nickName ?: fullName}"
println(informalGreeting) // Hi John Appleseed

Kotlinコードの?:Elvis構文と呼びます。

switch文

Swift
let vegetable = "red pepper"
switch vegetable {
case "celery":
    print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
    print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
    print("Is it a spicy \(x)?")
default:
    print("Everything tastes good in soup.")
}
// Is it a spicy red pepper?
Kotlin
val vegetable = "red pepper"
when (vegetable) {
    "celery" ->
        println("Add some raisins and make ants on a log.")
    "cucumber", "watercress" ->
        println("That would make a good tea sandwich.")
    else -> {
        if (vegetable.endsWith("pepper")) {
            println("Is it a spicy ${vegetable}?")    
        } else {
            println("Everything tastes good in soup.")
        }
    }
}

Kotlinのswitch文は、Swiftほどは、多種多様な比較演算をサポートしていないようです。

KotlinもSwiftと同様に、Javaのようにbreak;を書かなくてもフォールスルーしません。
コードが簡潔になって良いですよね。

関数とクロージャー

関数の基本構文

Swift
func greet(person: String, day: String) -> String {
    return "Hello \(person), today is \(day)."
}
print(greet(person: "Bob", day: "Tuesday")) // Hello Bob, today is Tuesday.
Kotlin
fun greet(person: String, day: String): String {
    return "Hello ${person}, today is ${day}."
}
println(greet(person = "Bob", day = "Tuesday")) // Hello Bob, today is Tuesday.

Kotlinも名前付きパラメータを取り入れています。
パラメータ名を省略する場合、Swiftでは関数側で_によって省略することを宣言しますが、Kotlinでは、以下のように呼び元側で省略します。

Swift
func greet(_ person: String, on day: String) -> String {
    return "Hello \(person), today is \(day)."
}
print(greet("John", on: "Wednesday")) // Hello John, today is Wednesday.
Kotlin
fun greet(person: String, day: String): String {
    return "Hello ${person}, today is ${day}."
}
println(greet("Bob", day = "Tuesday")) // Hello Bob, today is Tuesday.

Swiftはパラメータ変数名と引数のラベルを別の名前にできますが、Kotlinにはその機能はないようです。

タプル

Kotlinでは古いバージョンにはタプルがあったようですが、バージョンアップ時に削除されたとのこと。
(参考)https://blog.jetbrains.com/kotlin/2016/12/kotlin-1-1-m04-is-here/
値が2つだけのPairという形では残っています。
Kotlin -Pair

関数のネスト

Swift
func returnFifteen() -> Int {
    var y = 10
    func add() {
        y += 5
    }
    add()
    return y
}
print(returnFifteen()) // 15
Kotlin
fun returnFifteen() : Int {
    var y = 10
    fun add() {
        y += 5
    }
    add()
    return y
}
println(returnFifteen()) // 15

どちらも、内部関数から外部関数のローカル変数(つまりクロージャ)に対し演算することができます。

高階関数

Swift
func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(list: numbers, condition: {(number: Int) -> Bool in return number < 10})
// true
Kotlin
fun hasAnyMatches(list: List<Int>, condition: (Int) -> Boolean) : Boolean {
    for (item in list) {
        if (condition(item)) {
            return true
        }
    }
    return false
}
var numbers = listOf(20, 19, 7, 12)
hasAnyMatches(list = numbers, condition = fun(number: Int) : Boolean {return number < 10})
// true 

どちらも関数は第一級オブジェクトです。
関数の引数で無名関数を渡したり、戻り値として関数を受け取ったりは、どちらでもシンプルに書けます。

第二回はこちらです。
SwiftとKotlinの構文比較 (2) 〜クラス、列挙体、構造体、プロトコル、拡張

17
15
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
17
15