函数使您可以定义执行特定功能的可重用代码段。通常,函数能够接收一些值来修改其工作方式,但这不是必需的。
让我们从一个简单的函数开始:
代码语言:javascript复制func favoriteAlbum() {
print("My favorite is Fearless")
}
如果您将该代码放到playground上,将不会打印任何内容。是的,这是正确的。没有打印任何内容的原因是,我们已将“My favorite is Fearless”消息放置到名为favouriteAlbum()
的函数中,并且直到我们要求Swift运行favouriteAlbum()
函数时,该代码才会被调用。为此,请添加以下代码行:
favoriteAlbum()
该函数运行(或“调用(call)”)该函数,因此现在您将看到“My favorite is Fearless”打印出来。
如您所见,您可以通过编写func
来定义一个函数,然后编写函数名称,然后打开和关闭括号,然后再编写一段用打开和关闭花括号标记的代码。然后,您可以通过写入函数名称以及其后的右括号和右括号来调用该函数。
当然,这是一个无聊的例子——该函数无论做什么都执行相同的操作,因此它没有任何意义。但是,如果我们想每次打印不同的专辑怎么办?在这种情况下,我们可以告诉Swift我们希望函数在调用时接受一个值,然后在其中使用该值。
让我们现在开始:
代码语言:javascript复制func favoriteAlbum(name: String) {
print("My favorite is (name)")
}
这告诉Swift我们希望函数接受一个名为“ name”的值(称为“参数(parameter)”),该值应该是字符串。然后,我们使用字符串插值将喜爱的专辑名称直接写入输出消息中。要立即调用该函数,请编写以下代码:
代码语言:javascript复制favoriteAlbum(name: "Fearless")
鉴于它仍然只是一行代码,您可能仍然想知道关键是什么。好吧,想象一下我们在大型应用程序的20个不同地方使用了该功能,然后您的首席设计师出现并告诉您将消息更改为"I love Fearless so much – it's my favorite!''您是否真的要查找并更改代码中的所有20个实例?可能不会。使用函数,只需更改一次,一切都会更新。
您可以使函数接受任意数量的参数,因此让它接受名称和年份:
代码语言:javascript复制func printAlbumRelease(name: String, year: Int) {
print("(name) was released in (year)")
}
printAlbumRelease(name: "Fearless", year: 2008)
printAlbumRelease(name: "Speak Now", year: 2010)
printAlbumRelease(name: "Red", year: 2012)
这些函数参数名称很重要,实际上构成了函数本身的一部分。有时,您会看到多个具有相同名称的功能,例如handle()
,但具有不同的参数名称以区分不同的操作。
外部和内部参数名称
有时,您希望在调用函数时以一种方式命名参数,而在函数本身内部以另一种方式命名。这意味着当您调用一个函数时,它几乎使用自然的英语,但是在函数内部,参数具有合理的名称。此技术在Swift中经常使用,因此现在值得去学习和理解。
为了说明这一点,让我们编写一个函数,该函数可以打印字符串中的字母数。使用字符串的count
属性可以实现它,因此我们可以这样编写:
func countLettersInString(string: String) {
print("The string (string) has (string.count) letters.")
}
有了该功能,我们可以这样调用它:
代码语言:javascript复制countLettersInString(string: "Hello")
虽然确实可以,但是有点罗唆。另外,您也不会大声地说:“count letters in string string hello(计算字符串“Hello”字符串的字母数量)”。
Swift的解决方案是让您在调用参数时为其指定一个名称,并在方法内部指定另一个名称。要使用此功能,只需两次写入参数名称——一次用于外部,一次用于内部。
例如,我们可以在调用参数时将其命名为myString
,并在方法内部使用str
,如下所示:
func countLettersInString(myString str: String) {
print("The string (str) has (str.count) letters.")
}
countLettersInString(myString: "Hello")
您还可以指定下划线_
作为外部参数名称,以告诉Swift它根本不应该具有任何外部名称。例如:
func countLettersInString(_ str: String) {
print("The string (str) has (str.count) letters.")
}
countLettersInString("Hello")
如您所见,这使代码行看起来像一个英语句子:“count letters in string hello(计算“Hello”字符串的字母数量)”。
尽管在很多情况下使用_
是正确的选择,但是Swift程序员通常更喜欢命名其所有参数。仔细想想:为什么我们在函数中需要“ String”一词——我们还要在字母上计算什么?
因此,您通常会看到的是外部参数名称,例如“ in”,“ for”和“ with”,以及更有意义的内部名称。因此,编写此函数的“Swifty”方式如下所示:
代码语言:javascript复制func countLetters(in string: String) {
print("The string (string) has (string.count) letters.")
}
这意味着您使用参数名称“ in”调用该函数,这在函数内部将毫无意义。但是,在函数内部,相同的参数称为“字符串”,这很有用。因此,该函数可以这样调用:
代码语言:javascript复制countLetters(in: "Hello")
这才是真正的Swifty代码:“count letters in hello”看起来像自然的英语,但是代码也清晰明了。
PS: 在Swift社区中,短语 "Swifty code" 通常用于描述遵循当前最流行的约定的代码。
返回值
Swift函数可以通过在其参数列表之后写入->
然后是数据类型来返回值。完成此操作后,Swift将确保您的函数无论如何都将返回一个值,因此这又是您对代码的作用作出的保证。
例如,让我们编写一个函数,如果专辑是Taylor Swift的专辑之一,则返回true,否则返回false。这需要接受一个参数(要检查的专辑的名称),并将返回一个布尔值。这是代码:
代码语言:javascript复制func albumIsTaylor(name: String) -> Bool {
if name == "Taylor Swift" { return true }
if name == "Fearless" { return true }
if name == "Speak Now" { return true }
if name == "Red" { return true }
if name == "1989" { return true }
return false
}
如果您想尝试新的switch/case
知识,那么这个函数将是一个不错的选择。
现在,您可以通过传递专辑名称并根据结果执行操作来调用它:
代码语言:javascript复制if albumIsTaylor(name: "Red") {
print("That's one of hers!")
} else {
print("Who made that?!")
}
if albumIsTaylor(name: "Blue") {
print("That's one of hers!")
} else {
print("Who made that?!")
}
本文来自Hacking with Swift给swift初学者的入门课程Swift for Complete Beginners 的Functions