読み込み中...

Swiftでマスター!デフォルト引数の使い方と応用13選

Swiftのデフォルト引数の詳しい使い方と応用例を表すイメージ Swift
この記事は約23分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Swiftのプログラミングを学ぶ際、デフォルト引数は避けて通れないトピックの一つです。

デフォルト引数は、関数のパラメータに初期値を設定することができる機能で、これを利用すると、関数をより柔軟に、そして効率的に使用することができます。

この記事を読めば、Swiftのデフォルト引数の使い方や応用例、注意点といった、初心者から中級者、上級者までのレベルに応じた内容をしっかりとマスターすることができるでしょう。

●Swiftのデフォルト引数とは

Swiftでのデフォルト引数は、関数やメソッドの引数に初期値を設定する機能です。

この機能により、引数を省略して関数を呼び出すことが可能になり、コードの可読性や使いやすさが向上します。

例えば、ある関数が3つの引数を取る場合でも、デフォルト引数を設定しておけば、それを省略して2つの引数だけで関数を呼び出すことができます。

これにより、同じ関数でも異なるシチュエーションで使い分けることができるのです。

○デフォルト引数の基本

Swiftでデフォルト引数を設定する際の基本的な書き方は、関数を定義する際に引数として初期値を設定するだけです。

これにより、その引数が省略された際に、自動的に設定された初期値が使われるようになります。

例として、あるメッセージを表示する関数を考えてみましょう。

しかし、特定の条件下では異なるメッセージを表示したいという場合、デフォルト引数を用いて簡潔にコードを書くことができます。

// メッセージを表示する関数、デフォルト引数を設定
func displayMessage(name: String, message: String = "こんにちは") {
    print("\(name)さん、\(message)")
}

このコードでは、displayMessage関数はnamemessageの2つの引数を取ります。

そして、message引数には”こんにちは”というデフォルト引数が設定されています。

これにより、message引数を省略して関数を呼び出すことが可能になります。

// デフォルト引数を使用して関数を呼び出す
displayMessage(name: "太郎")

これを実行すると、”太郎さん、こんにちは”と表示されます。

もちろん、message引数を指定して呼び出すことも可能です。

// デフォルト引数をオーバーライドして関数を呼び出す
displayMessage(name: "太郎", message: "こんばんは")

これを実行すると、”太郎さん、こんばんは”と表示されるわけです。

このようにデフォルト引数を設定することで、同じ関数を異なるパラメータで簡潔に呼び出すことが可能になるのです。

●デフォルト引数の使い方

Swiftのデフォルト引数の魅力はその使い勝手の良さにあります。

特定の引数に初期値を与えることで、関数の呼び出し時にその引数の指定を省略できるのです。

こうすることで、コードが簡潔になり、可読性も上がります。

さらに、関数の多様性も増すため、一つの関数で複数のシチュエーションに対応することが可能になります。

○サンプルコード1:基本的な関数にデフォルト引数を設定する

デフォルト引数を設定する方法を見ていきましょう。

下記のサンプルコードは、ある商品の価格を表示しています。

func showPrice(of item: String, price: Int = 1000) {
    print("\(item)の価格は\(price)円です。")
}

このコードでは、showPrice関数はitempriceの2つの引数を取ります。

そして、price引数には1000というデフォルト引数が設定されています。

関数を呼び出すときにpriceを指定しなければ、デフォルトの1000円が自動的に使用されます。

showPrice(of: "りんご")

この関数を実行すると、”りんごの価格は1000円です。”と表示されます。

○サンプルコード2:複数のデフォルト引数を持つ関数

複数の引数にデフォルト値を設定することもできます。

下記のコードは、複数のフルーツの価格を表示しています。

func showFruitPrices(apple: Int = 200, banana: Int = 100, orange: Int = 150) {
    print("リンゴ: \(apple)円, バナナ: \(banana)円, オレンジ: \(orange)円")
}

関数を呼び出す際、引数を省略すれば、デフォルトの価格が表示されます。

showFruitPrices()

これを実行すると、”リンゴ: 200円, バナナ: 100円, オレンジ: 150円”と表示されるでしょう。

○サンプルコード3:デフォルト引数と通常の引数の組み合わせ

デフォルト引数と通常の引数を組み合わせて関数を定義することも可能です。

この場合、デフォルト引数を持つ引数は最後に配置することが一般的です。

次のサンプルコードでは、特定のアイテムとその価格、及び数量を表示しています。

func showItemDetail(name: String, quantity: Int, price: Int = 500) {
    let total = price * quantity
    print("\(name)を\(quantity)個で、合計\(total)円です。")
}

関数を以下のように呼び出すことで、指定したアイテムの詳細が表示されます。

showItemDetail(name: "ノート", quantity: 3)

このコードを実行すると、”ノートを3個で、合計1500円です。”という結果が表示されることでしょう。

こうしたデフォルト引数の設定により、関数の使い勝手が飛躍的に向上します。

●デフォルト引数の応用例

Swiftのデフォルト引数は、初めてのユーザーから経験豊富なプロの開発者まで幅広く利用されています。

ここでは、デフォルト引数のさまざまな応用例を紹介します。

これらの応用例を理解することで、デフォルト引数の真価と、それがどれほどの可能性を持っているかを深く理解することができるでしょう。

○サンプルコード4:初期値を設定しながら関数をオーバーロードする

Swiftの関数オーバーロードは、同じ関数名を持つ複数の関数を定義することが許可されている機能です。

デフォルト引数と組み合わせることで、さらに多彩な関数の定義が可能になります。

func displayMessage(_ message: String, times: Int = 1) {
    for _ in 0..<times {
        print(message)
    }
}

func displayMessage(_ message: String, prefix: String) {
    print(prefix + message)
}

このコードでは、displayMessageという名前の関数を二つ定義しています。

一つ目の関数は、メッセージを指定された回数分繰り返し表示するもので、times引数にはデフォルト引数が設定されています。

二つ目の関数は、メッセージの前にプレフィックスを追加して表示するものです。

displayMessage("こんにちは")
displayMessage("こんにちは", times: 3)
displayMessage("こんにちは", prefix: "重要:")

このコードを実行すると、次の結果が得られます。

こんにちは
こんにちは
こんにちは
こんにちは
重要:こんにちは

○サンプルコード5:デフォルト引数を使用した構造体のイニシャライザ

デフォルト引数は、クラスや構造体のイニシャライザでも利用できます。

これにより、オブジェクトの初期化を柔軟に行うことが可能となります。

下記のサンプルコードでは、Rectangleという構造体が定義されています。

struct Rectangle {
    var width: Double
    var height: Double

    init(width: Double = 1.0, height: Double = 1.0) {
        self.width = width
        self.height = height
    }
}

Rectangle構造体のイニシャライザは、幅と高さの2つの引数を取りますが、それぞれの引数にはデフォルト引数が設定されています。

let rect1 = Rectangle()
let rect2 = Rectangle(width: 5.0)
let rect3 = Rectangle(height: 10.0)
let rect4 = Rectangle(width: 5.0, height: 10.0)

このコードでは、デフォルト引数を利用して、さまざまな方法でRectangle構造体のインスタンスを生成しています。

○サンプルコード6:可変引数とデフォルト引数の組み合わせ

Swiftでの関数定義において、特定の引数を可変引数として設定することができます。

これにより、同じ引数名で複数の値を渡すことが可能となります。

さらに、デフォルト引数との組み合わせにより、関数の汎用性と柔軟性を向上させることができます。

下記のサンプルコードでは、可変引数とデフォルト引数を組み合わせた関数を定義しています。

func printNumbers(prefix: String = "数値:", numbers: Double...) {
    for num in numbers {
        print("\(prefix) \(num)")
    }
}

このコードでは、printNumbers関数はprefixという名前のデフォルト引数と、numbersという名前の可変引数を持っています。

prefix引数にはデフォルトで”数値:”という文字列が設定されており、numbers引数は可変引数として任意の数のDouble型の値を受け取ることができます。

下記のサンプルコードは、この関数の使用例です。

printNumbers(numbers: 1.0, 2.5, 3.7)
printNumbers(prefix: "Value:", numbers: 4.5, 5.6)

上記のコードを実行すると、関数は次のような出力を生成します。

数値: 1.0
数値: 2.5
数値: 3.7
Value: 4.5
Value: 5.6

○サンプルコード7:デフォルト引数を持つクロージャ

Swiftのクロージャは、独立したコードブロックとして機能するもので、デフォルト引数を使用することが可能です。

この機能により、クロージャの呼び出しをより柔軟に行うことができます。

下記のサンプルコードでは、デフォルト引数を持つクロージャの例を表しています。

let greet: (String, String?) -> Void = { name, greeting in
    let greetWord = greeting ?? "こんにちは"
    print("\(greetWord)、\(name)さん!")
}

greet("太郎", nil)
greet("花子", "こんばんは")

このコードのクロージャgreetは、2つのString型の引数を持ち、そのうちの1つはオプショナル型です。

オプショナルのデフォルト値として”こんにちは”が設定されています。

上記のコードを実行すると、次のような結果が得られます。

こんにちは、太郎さん!
こんばんは、花子さん!

○サンプルコード8:配列やディクショナリをデフォルト引数として設定

Swiftの関数やメソッドの引数として、デフォルトの配列やディクショナリを設定することが可能です。

これにより、関数の呼び出し時に特定の引数を省略した場合、デフォルトの値が使用されることになります。

特に、初期設定や共通の設定値を関数内で使用する際に、この機能は非常に便利です。

下記のサンプルコードでは、配列とディクショナリをデフォルト引数として関数に設定しています。

func displayInformation(names: [String] = ["未設定"], details: [String: String] = ["年齢": "不明", "住所": "不明"]) {
    for name in names {
        print("名前: \(name)")
    }
    for (key, value) in details {
        print("\(key): \(value)")
    }
}

このコードでは、displayInformationという関数を定義しています。

この関数はnamesという名前のデフォルト引数と、detailsという名前のディクショナリ型のデフォルト引数を持っています。

引数を指定せずに関数を呼び出すと、デフォルトの値が使用されます。

下記のサンプルコードは、この関数の使用例です。

displayInformation()
displayInformation(names: ["山田太郎", "佐藤花子"], details: ["年齢": "25歳", "住所": "東京都"])

上記のコードを実行すると、最初のdisplayInformation関数の呼び出しではデフォルトの値が使用され、次の結果が表示されます。

名前: 未設定
年齢: 不明
住所: 不明

次に、引数を指定して関数を呼び出すと、指定した引数の値が使用され、次の結果が表示されます。

名前: 山田太郎
名前: 佐藤花子
年齢: 25歳
住所: 東京都

このように、Swiftでのデフォルト引数の設定を活用することで、関数の呼び出しをより柔軟に行うことができます。

○サンプルコード9:デフォルト引数を用いた再帰関数

再帰関数は、自分自身を呼び出す関数のことを指します。Swiftでは、デフォルト引数を用いた再帰関数も作成することができます。

デフォルト引数を使用することで、関数の初回呼び出し時に特定の値をセットすることができ、それを基に再帰的な処理を実行することができます。

下記のサンプルコードでは、デフォルト引数を持つ再帰関数を使用して、指定した数までの階乗を計算する関数を実装しています。

func factorial(_ n: Int, current: Int = 1, accumulator: Int = 1) -> Int {
    if current > n {
        return accumulator
    }
    return factorial(n, current: current + 1, accumulator: current * accumulator)
}

このコードでは、factorial関数を定義しています。

この関数は、指定した数nまでの階乗を計算するものであり、再帰的に自身を呼び出す構造になっています。

デフォルト引数としてcurrentaccumulatorを設定しており、これらの引数は関数の再帰処理を補助するために使用されます。

下記のサンプルコードは、この関数の使用例です。

let result = factorial(5)
print("5の階乗は\(result)です。")

上記のコードを実行すると、次の結果が表示されます。

5の階乗は120です。

○サンプルコード10:クラスのメソッド内でのデフォルト引数の使用

Swiftでは、関数だけでなく、クラスや構造体のメソッド内でもデフォルト引数を使用することが可能です。

これにより、オブジェクト指向プログラミングの際に、メソッドの使い勝手を向上させることができます。

下記のサンプルコードでは、Personというクラス内のメソッドでデフォルト引数を設定しています。

class Person {
    var name: String
    var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    // メソッド内でのデフォルト引数の使用
    func introduce(to person: String = "友人") {
        print("\(name)は\(person)に、自分は\(age)歳であると紹介します。")
    }
}

このコードでは、introduceというメソッドがデフォルト引数personを持っています。

このメソッドは、あるPersonオブジェクトが自己紹介をする際に使用されます。

下記のサンプルコードは、このクラスとメソッドの使用例です。

let taro = Person(name: "太郎", age: 25)
taro.introduce()
taro.introduce(to: "花子")

上記のコードを実行すると、最初のintroduceメソッドの呼び出しではデフォルトの友人という値が使用され、次のような結果が表示されます。

太郎は友人に、自分は25歳であると紹介します。

次に、to: "花子"という引数を指定してメソッドを呼び出すと、指定した引数の値が使用され、次の結果が表示されます。

太郎は花子に、自分は25歳であると紹介します。

このように、Swiftのクラスのメソッド内でデフォルト引数を使用することで、メソッドの多様性を保ちつつ、簡潔なコードを実現することができます。

○サンプルコード11:デフォルト引数をもつプロトコルのメソッド

プロトコルは、Swiftでのインターフェースを定義するための仕組みです。

プロトコル内でメソッドを定義する際、デフォルト引数を持つことはできませんが、拡張(extension)を使用してデフォルトの実装を提供し、その中でデフォルト引数を活用することができます。

下記のサンプルコードでは、Greetingというプロトコルとその拡張を使用して、デフォルト引数を持つメソッドを実現しています。

protocol Greeting {
    func greet(name: String)
}

extension Greeting {
    // デフォルト引数を持つメソッドの実装
    func greet(name: String = "ゲスト") {
        print("こんにちは、\(name)さん!")
    }
}

class Japanese: Greeting {}

let japanese = Japanese()
japanese.greet()
japanese.greet(name: "太郎")

このコードでは、Greetingプロトコル内のgreetメソッドが拡張によってデフォルト引数を持つ形で実装されています。

そして、このプロトコルを採用するJapaneseクラスを定義しています。

上記のコードを実行すると、最初のgreetメソッドの呼び出しではデフォルトのゲストという値が使用され、次のような結果が表示されます。

こんにちは、ゲストさん!

次に、name: "太郎"という引数を指定してメソッドを呼び出すと、指定した引数の値が使用され、次の結果が表示されます。

こんにちは、太郎さん!

○サンプルコード12:エラー処理とデフォルト引数の組み合わせ

Swiftにおけるエラー処理は非常に強力であり、多くのシチュエーションでのエラーを簡単に処理することが可能です。

特に、デフォルト引数との組み合わせを利用することで、さらに柔軟性を持ったエラー処理を実装することができます。

下記のサンプルコードは、デフォルト引数とエラー処理を組み合わせた関数の例を表しています。

enum InputError: Error {
    case invalidValue
}

func processInput(_ value: Int? = nil) throws {
    guard let v = value, v > 0 else {
        throw InputError.invalidValue
    }
    print("入力された値は\(v)です")
}

このコードでは、InputErrorというエラー型を定義し、processInput関数でデフォルト引数を持つ入力値を受け取ります。

受け取った入力値がnilまたは0以下の場合、エラーをスローします。

下記の実行コードは、上記の関数を呼び出す際の例を表しています。

do {
    try processInput()
} catch {
    print("エラー: 不正な値が入力されました")
}

do {
    try processInput(5)
} catch {
    print("エラー: 不正な値が入力されました")
}

上記のコードを実行すると、最初のprocessInput関数の呼び出しでは、デフォルト引数としてnilが渡されるため、エラーがスローされ、”エラー: 不正な値が入力されました”と表示されます。

次に、5という値を引数として関数を呼び出すと、この値は正常であるため、エラーはスローされず、”入力された値は5です”と表示されます。

このように、Swiftではデフォルト引数とエラー処理を組み合わせることで、関数内での入力値の検証やエラーハンドリングを簡潔に行うことができます。

○サンプルコード13:デフォルト引数を用いた高階関数

Swiftの高階関数は、関数を引数として受け取ったり、関数を返したりする関数です。

デフォルト引数と組み合わせることで、より多様な用途での利用が可能となります。

下記のサンプルコードは、高階関数を使用し、デフォルト引数を持つ関数を引数として受け取る例を表しています。

func operateOnNumbers(_ a: Int, _ b: Int, operation: (Int, Int) -> Int = (+)) -> Int {
    return operation(a, b)
}

このコードでは、operateOnNumbersという関数が2つの整数と、それらの整数に対する操作を行う関数を引数として受け取ります。

操作を行う関数にはデフォルト引数として加算が設定されています。

下記の実行コードは、上記の関数を使用した例です。

let result1 = operateOnNumbers(3, 5)
let result2 = operateOnNumbers(3, 5, operation: (*))

上記のコードを実行すると、result1にはデフォルトの加算が適用され、結果として8が返されます。

一方、result2では乗算の操作が適用され、結果として15が返されます。

●注意点と対処法

Swiftのデフォルト引数を使用する際、初心者から上級者まで多くのプログラマーが陥りやすいいくつかのトラップが存在します。

ここでは、デフォルト引数を安全かつ効率的に利用するための主要な注意点と、それに対する対処法を詳しく紹介します。

○引数の順序の誤解

デフォルト引数は関数の中で自由に配置することができますが、その配置によって関数の呼び出し方が変わる可能性があります。

例えば、次のような関数を考えてみましょう。

func greet(name: String = "太郎", age: Int) {
    print("\(name)さんは\(age)歳です。")
}

この関数では、nameにデフォルト引数が設定されていますが、ageには設定されていません。

この関数を呼び出す場合、次のようにする必要があります。

greet(age: 25)  // 出力:太郎さんは25歳です。

ここで注意すべき点は、デフォルト引数が設定されているnameを省略しても、他の引数の名前は必ず指定して関数を呼び出す必要があるということです。

○デフォルト引数の再評価

デフォルト引数は関数が呼び出されるたびに再評価されることを理解しておく必要があります。

特に、デフォルト引数に計算や関数の呼び出しを使用する場合、その計算や関数は関数が呼び出されるたびに実行されます。

次のサンプルコードを考えてみましょう。

func printTimestamp(with message: String, timestamp: Int = getCurrentTimestamp()) {
    print("[\(timestamp)] \(message)")
}

func getCurrentTimestamp() -> Int {
    return Int(Date().timeIntervalSince1970)
}

この例では、printTimestamp関数のデフォルト引数としてgetCurrentTimestamp関数が設定されています。

そのため、printTimestamp関数を呼び出すたびに、現在のタイムスタンプが取得されます。

このような動作を意識せずに使用すると、予期しない結果やパフォーマンスの低下を引き起こす可能性があるため、注意が必要です。

○デフォルト引数とオーバーロードの競合

関数のオーバーロードとデフォルト引数を併用する場合、どの関数が呼び出されるのかが明確でない場合があります。

そのような場合、コンパイラエラーが発生することがあります。

例えば、次のような2つの関数を考えてみましょう。

func displayMessage(_ message: String) {
    print(message)
}

func displayMessage(_ message: String = "Hello!") {
    print("Default: \(message)")
}

上記の関数は、デフォルト引数を持つバージョンと持たないバージョンの2つのdisplayMessage関数を定義しています。

この状態でdisplayMessage()を呼び出すと、どちらの関数を呼び出すべきかが不明確になるため、エラーが発生します。

このような状況を避けるためには、関数のオーバーロードとデフォルト引数を適切に組み合わせるか、明確に区別できるように関数名を変更するなどの対策が必要です。

●カスタマイズ方法

Swiftでデフォルト引数を活用すると、関数やメソッドの呼び出しをより柔軟に、かつコードの冗長性を減少させることができます。

しかし、基本的な使い方だけでなく、より高度なカスタマイズ方法を知っておくことで、プログラムの品質や効率を一層向上させることができます。

○変数や定数をデフォルト引数として設定する

Swiftでは、関数やメソッドのデフォルト引数に変数や定数を指定することができます。

これにより、動的にデフォルト値を設定することが可能となります。

このコードではuserNameという定数をデフォルト引数として利用して、挨拶するメッセージを表示する関数を表しています。

let userName = "鈴木"

func greeting(name: String = userName) {
    print("こんにちは、\(name)さん!")
}

// 関数の呼び出し
greeting()  // 出力:こんにちは、鈴木さん!

この例では、greeting関数を引数なしで呼び出すと、デフォルト引数として指定されたuserNameの値が使用されます。

○クロージャをデフォルト引数として利用する

クロージャをデフォルト引数として設定することも可能です。

これにより、関数の呼び出し時に動的な処理を実行することができます。

このコードでは、デフォルト引数としてクロージャを設定し、そのクロージャ内で文字列を生成する関数を表しています。

func showMessage(generator: () -> String = { "今日は晴れです。" }) {
    let message = generator()
    print(message)
}

// 関数の呼び出し
showMessage()  // 出力:今日は晴れです。

この例では、showMessage関数を引数なしで呼び出すと、デフォルト引数として指定されたクロージャが実行され、”今日は晴れです。”というメッセージが表示されます。

○デフォルト引数の再設定

Swiftでは、デフォルト引数を持つ関数の呼び出し時に、そのデフォルト引数を再設定することもできます。

これにより、必要に応じて関数の動作を変更することが可能となります。

このコードでは、greet関数のデフォルト引数を再設定して、異なるメッセージを表示する方法を示しています。

func greet(message: String = "こんにちは") {
    print(message)
}

// 関数の呼び出し
greet()          // 出力:こんにちは
greet(message: "こんばんは")  // 出力:こんばんは

この例では、デフォルト引数の”こんにちは”というメッセージの代わりに、”こんばんは”というメッセージを指定してgreet関数を呼び出しています。

まとめ

Swiftのデフォルト引数は、関数やメソッドを呼び出す際の柔軟性を高め、コードの冗長性を減少させる強力なツールです。

この機能を使用することで、引数が与えられなかった場合のデフォルトの振る舞いを簡単に定義することができます。

本記事では、デフォルト引数の基本的な使い方から、さまざまな応用例、カスタマイズ方法までを網羅的に解説しました。

特に、動的なデフォルト値の設定やクロージャの利用、再設定の方法など、多岐にわたる応用方法を学ぶことができたかと思います。

プログラミング初心者から上級者まで、Swiftでのデフォルト引数の効果的な利用方法を理解し、実際のコードに取り入れることで、より洗練されたプログラムを作成する手助けとなることを期待しています。

デフォルト引数は非常に便利な機能ではありますが、過度な使用はコードの可読性を低下させる可能性もあります。

適切な場面での利用と、他の開発者とのコードの共有を意識しながら、デフォルト引数をうまく活用してください。