関数のさまざまな引数
Swiftでは、Objective-Cより進歩した引数宣言が可能になっています。それらを紹介しましょう。
外部引数名宣言
Objective-Cのメソッドの多くは、2つ目の引数以降に、引数を説明するようなラベルがつけられていました。
NSObject *obj = [NSObject new]; [obj performSelector: @selector(description) withObject: nil afterDeley: 1.0f]; //各引数をラベルで説明する
Swiftにも、関数呼び出しの際、説明的に引数にラベルを付与できる外部引数名宣言があります。先ほどのコード例で見たmultiprint関数を、外部引数名宣言を使って宣言しなおしてみましょう。
func multiprint(string content: String, withTimes times: UInt) { for _ in 1...times { print(content) } } multiprint(string: "Good!", withTimes: 10)
内部引数「content」「times」の前に、それぞれ「string」「withTimes」というラベルがつけられています。外部(関数を呼び出す側)から見て、関数の意味がわかりやすくなったと思いませんか。
外部引数名宣言の略記法
Swiftには、「#」を使った外部引数名宣言の略記法があります。先ほどのmultiprint関数を略記法で宣言すると、次のとおりになります。
func multiprint(#string: String, #withTimes: UInt) { for _ in 1...withTimes { print(string) } }
このコードは、次のように宣言するのと同等です。
func multiprint(string string: String, withTimes withTimes: UInt) { for _ in 1...withTimes { print(string) } }
つまり、略記法では、外部引数名と内部引数名が等しく宣言されます。Objective-Cに比べ、宣言もしやすくなりましたね。
引数のデフォルト値
Swiftの関数には、引数のデフォルト値も設定できるようにもなりました。引数宣言の後に、デフォルト値を付与するだけです。
func multiprint(#string: String, withTimes: UInt = 5) { for _ in 1...withTimes { print(string) } } multiprint(string: "Good!! ") // Good!! Good!! Good!! Good!! Good!! multiprint(string: "Well Done!! ", withTimes: 3) // Well Done!! Well Done!! Well Done!!
可変長引数
引数の型宣言の後に...をつけることで、可変長引数を持った関数を宣言することができます。
func concatStrs(strs: String...) -> String { var mStr = "" for str in strs { mStr += str } return mStr } concatStrs("Good", " ", "night", " ", "!!") // Good night !!
このとき、引数strsはArray
一般に、T型の値を可変長引数としてT...で宣言することで、関数内部ではArray<T>として扱うことができます。va_listなどのC言語のマクロを駆使して可変長引数の関数を扱っていたこれまでと比べると、シンプルに実装できそうです。
なお、可変長引数を扱う際には、次の2点を満たさなくてはならないことに注意してください。
- 引数宣言の末尾であること
- 複数の可変長引数は1つの関数に宣言しないこと
また、関数の引数は、デフォルトでは定数として宣言されます。そのため、関数の引数に代入しようとすると、letで宣言された変数に代入しようとするときと同じくエラーになります。引数を関数内で変数として扱うには、引数宣言の前にvarを置きます。
次のbuildString関数は、先ほどの例のconcatStrs関数と内部の処理はほとんど同じですが、引数宣言の前にvarを置くことで、concatStrs関数の先頭で行っていた変数宣言(var mStr = "")を省くことが可能になります。
func buildString(var string: String, #withStrings: [String]) -> String { for str in withStrings { string += str } return string } buildString("a", withStrings:["r", "ra", "y"]) // "array"
引数宣言の前にinoutキーワードを置くと、C言語の関数におけるポインタ引数のように値型を扱うことが可能になります。次のコードでは、関数内部でinoutのついた引数を、あたかもポインタのように扱ってString値を入れ替えています。
func swapStr(inout aStr: String, inout bStr: String) { let tempAStr = aStr aStr = bStr bStr = tempAStr } var food = "food" var human = "human" println(food + " made " + human) // "food made human" swapStr(&food, &human) println(food + " made " + human) // "human made food"