inout
Swiftにはポインタという概念がありませんが、inoutを使うことで、関数の引数をポインタとして受け取り値を直接いじるCのような書き方ができます。
inoutを使用した関数の呼び出し方は、普通の関数と違って以下のように実引数の変数の前に&をつけて呼ぶことになります(ただし、&はC言語と同じようにアドレスを示すものではありません)。
func square(inout x:Int, inout y:Int) {
x = x * x
y = y * y
}
/* 以下呼び出し側 */
var x = 2
var y = 4
square(&x, &y) // x=4, y=16になる
しかし、Swiftはタプルを使うことによって、返り値を複数指定できるため、inoutを使わなくても複数の値を返す関数を定義することができます(引数に構造体を指定することでも、複数の値を返すことができます)。
func square(x:Int, y:Int) -> (Int, Int) {
return (x * x, y * y)
}
/* 以下呼び出し側 */
var x = 2
var y = 4
var res = square(x, y) // res.0=4, res.1=16になる
外部引数名
Swiftでは、関数を呼び出す際に引数の意味が伝わるよう、引数にキーワード(外部引数名)をつけることができます。
// 以下のように外部引数名(widthとheight)をつけることができる。
// wとhを内部引数名と呼ぶ。
func area(width w:Int, height h:Int) -> Int {
return w * h
}
/* 以下呼び出し側 */
// 呼び出し側の実引数が何を表しているのかが明確になる。
let res = area(width: 5, height: 6)
また、以下のように仮引数の前に#
を書くことで、内部引数名と外部引数名を同じにすることもできます。
func area(#width:Int, #height:Int) -> Int {
return width * height
}
/* 以下呼び出し側 */
let res = area(width: 5, height: 6)
引数に用いるvar
Swiftでは、基本的に関数の引数の値を関数内で変更することができません。
しかし、仮引数の前にvar
を書くことで変更可能になります。
func area(var width:Int, var height:Int) -> Int {
// 引数の値を変更できる。
width += 1
height += 1
return width * height
}
/* 以下呼び出し側 */
var w = 5
var h = 6
let res = area(w, h) // res=42
// w, hはそれぞれ5, 6のまま
同様にlet
を書くこともできますが、これは何も書かないときと同じなので、変更しないことを明示的に示したいときに使います。
オーバーロード
Swiftでは、以下のいずれかが異なれば、同名の関数を定義することができます。
- 引数の個数
- 引数の型
- 返り値の型
- 外部引数名
したがって、以下のすべてを定義してもコンパイルエラーになりません。
func area(w:Int, h:Int) -> Int {
...
}
// 引数の個数が異なる
func area(a:Int, b:Int, h:Int) -> Int {
...
}
// 引数の型が異なる
func area(w:Double, h:Double) -> Int {
...
}
// 返り値の型が異なる
func area(w:Int, h:Int) -> Double {
...
}
// 外部引数名が異なる
func area(width w:Int, height h:Int) -> Int {
...
}
// 外部引数名が異なる
func area(hoge w:Int, foo h:Int) -> Int {
...
}
ただし、呼び出し側で引数や返り値の型を意識する必要があります。
var w = 5
var h = 6
// let res = area(w, h) コンパイルエラー
// area関数にはIntを返すものとDoubleを返すものとがあるため、
// resの型がわからないとどの関数を呼べばいいかわからない
// 型をちゃんと指定する
let res : Int = area(w, h)