Swift入门:枚举

2020-03-20 16:02:54 浏览数 (1)

枚举(Enumerations)通常称为“ enum”,发音为“ ee-num”,是一种在Swift中定义自己的值的方法。在某些编程语言中,它们只是简单的小事,但是Swift给它们增加了巨大的功能。

让我们从前面的一个简单示例开始:

代码语言:javascript复制
func getHaterStatus(weather: String) -> String? {
    if weather == "sunny" {
        return nil
    } else {
        return "Hate"
    }
}

该函数接受定义当前天气的字符串。问题是,对于这种类型的数据,字符串不是好的选择-是"rain'',“rainy''还是”raining''?还是“ showering(阵雨)”,“ drizzly(蒙蒙细雨)”或“ stormy(暴风雨)”?更糟糕的是,如果一个人用大写的R写下“ Rain”,而其他人却不在乎键入的内容,而又写下“ Ran”怎么办?

枚举通过让您定义一个新的数据类型,然后定义它可以容纳的可能值来解决此问题。例如,我们可以说有五种天气:sun, cloud, rain, wind 和 snow。如果我们将其设为枚举,则意味着Swift将仅接受这五个值-其他任何情况都会触发错误。在幕后,枚举通常只是简单的数字,比计算机使用的字符串要快得多。

让我们将其放入代码中:

代码语言:javascript复制
enum WeatherType {
    case sun, cloud, rain, wind, snow
}

func getHaterStatus(weather: WeatherType) -> String? {
    if weather == WeatherType.sun {
        return nil
    } else {
        return "Hate"
    }
}

getHaterStatus(weather: WeatherType.cloud)

看一下前三行:第1行为我们的类型命名为WeatherType。这就是您将在代码中代替StringInt的内容。正如我已经概述的那样,第2行定义了我们的枚举可能出现的五种情况。约定以小写字母开头,因此“ sun”,“ cloud”等。第3行只是一个大括号,结束了枚举。

现在看一下它的用法:我修改了getHaterStatus()使其具有WeatherType值。条件语句也被重写以与WeatherType.sun进行比较,这是我们的值。请记住,此检查只是幕后的数字,闪电般快。

现在,返回并再次阅读该代码,因为我将通过两个重要的更改来重写它。

代码语言:javascript复制
enum WeatherType {
    case sun
    case cloud
    case rain
    case wind
    case snow
}

func getHaterStatus(weather: WeatherType) -> String? {
    if weather == .sun {
        return nil
    } else {
        return "Hate"
    }
}

getHaterStatus(weather: .cloud)

我修改了两个地方。首先,每种天气类型现在都在单独一行。这似乎是一个很小的更改,在这个示例中确实如此,但是很快就变得很重要。第二个变化是我在weather == .sun的情况下写的——我不需要拼写出完整的WeatherType.sun,因为Swift知道我正在与WeatherType`变量进行比较,因此它使用类型推断。

枚举在switch / case块内特别有用,特别是因为Swift知道您的枚举可以拥有的所有值,因此可以确保覆盖所有这些值。例如,我们可以尝试将getHaterStatus()方法重写为:

代码语言:javascript复制
func getHaterStatus(weather: WeatherType) -> String? {
    switch weather {
    case .sun:
        return nil
    case .cloud, .wind:
        return "dislike"
    case .rain:
        return "hate"
    }
}

是的,我意识到“ haters gonna dislike”并不是一个好主意,但无论如何它是学术性的,因为此代码无法构建因为它没有处理.snow的case,Swift希望涵盖所有case。您要么为此添加一个案例,要么添加一个default:

带有附加值的枚举 (关联值枚举)

Swift最强大的功能之一是枚举可以具有您定义的附加值。为了进一步扩展这个越来越令人怀疑的示例,我将为.wind案例添加一个值,以便我们可以说风速有多快。修改您的代码为如下:

代码语言:javascript复制
enum WeatherType {
    case sun
    case cloud
    case rain
    case wind(speed: Int)
    case snow
}

如您所见,其他情况不需要速度值——我只是把它放在wind中。现在是真正的魔力:Swift让我们在·switch / case·块中添加了附加条件,以便仅当这些条件为true时,case才会匹配。它使用let关键字访问案例中的值,然后使用where关键字进行模式匹配。

这是新函数:

代码语言:javascript复制
func getHaterStatus(weather: WeatherType) -> String? {
    switch weather {
    case .sun:
        return nil
    case .wind(let speed) where speed < 10:
        return "meh"
    case .cloud, .wind:
        return "dislike"
    case .rain, .snow:
        return "hate"
    }
}

getHaterStatus(weather: WeatherType.wind(speed: 5))

您可以看到.wind出现了两次,但是只有当风速低于每小时10公里时,第一次出现。如果风等于或大于10,则不会匹配。关键是您可以使用let获取枚举中的值(即声明一个可以引用的常量名称),然后使用where条件进行检查。

Swift会从上到下评估 switch/case ,并在找到匹配项后立即停止。这意味着,如果case .cloud,.wind:出现在case .wind(let speed) where speed < 10:之前,则将代替执行——同时输出更改。

因此,请仔细考虑如何给case排序!

提示:Swift的可选参数实际上是使用关联值枚举实现的。有两种情况:nonesomesome具有可选值内的值。

本文来自Hacking with Swift给swift初学者的入门课程Swift for Complete Beginners 的Optional Chaining

< Previous: 可选链

Swift 入门 Home

Next: 结构体 >

0 人点赞