Swift中的枚举
在Swift中,我们具有一流的类型:类,结构,协议和枚举。 这样,我们就可以在拥有清晰可读的代码的同时创建令人惊奇的事物。
本文将为您介绍以下主题:何时使用枚举,其语法,枚举的类型,对其进行迭代,枚举的属性和方法,关联值以及比较枚举。 希望您是口袋妖怪迷。
何时使用枚举
如果需要对相关值进行分组,则可以使用枚举。 在下面的示例中,我们将创建一个Pokemon类并定义“ Type”。 (请注意,代码中的Type称为Kind)
神奇宝贝课程 {
/// Pokedex号
让指数:整数
///宠物小精灵的名字
变量名称:字符串
初始化 (索引:整数,名称:字符串){...}
}
我们的Pokemon类是用pokedex编号 (索引)和name属性设置的。 我们要添加类型(火,草,水等)属性。
我们可能会考虑使用结构来定义类型。
宠物小精灵扩展名 {
struct Kind {
//类型名称
变量名称:字符串
}
}
但是我们对这种方法有疑问。
1.我们允许任何字符串成为神奇宝贝类型
2.比较变得复杂
让 pokemonElectricType = Pokemon.Kind(name:“ Electric”)
让 pokemonElectric2Type = Pokemon.Kind(name:“ Electric”)
//这不起作用😬
打印(pokemonElectricType == pokemonElectric2Type)
//检查字符串var“ name”起作用
打印(pokemonElectricType.name == pokemonElectric2Type.name)
//这不可能
让 nonsenseType = Pokemon.Kind(name:“无意义”)
我们当然可以使用这种方法,但是使用枚举会更干净。
句法
使用关键字enum ,然后使用案例进行定义。 对于口袋妖怪的类型,我们将为每种类型编写一个案例。
宠物小精灵扩展名 {
枚举种类{
外壳电,火,水,草
}
}
更好! 我们可以删除Type结构并使用我们的枚举。
我们不允许其他开发人员使用我们的代码创建随机的Pokemon类型。 另外,比较类型更容易,我们不比较字符串。
神奇宝贝类 {
/// Pokedex号
让指数:整数
///宠物小精灵的名字
变量名称:字符串
///口袋妖怪的类型
var type:类型
初始化 (索引:整数,名称:字符串,类型:类型){
自我 .index =索引
自我 .name =名称
自我 .type =类型
}
}
let pikachu = Pokemon(索引:25,名称:“ Pikachu”,键入:.electric)
如果 pikachu.type == .electric {
print(“ \(pikachu.name)是Electric”)
}
请注意,初始化Pokemon对象时不必编写Pokemon.Type.electric。
枚举RawValues
枚举可以具有定义的类型。 此类型与每种情况相关联,并用称为rawValue的属性表示 。
可以将符合RawRepresentable协议的对象定义为Enum类型。 我们可以使用与枚举类型关联的对象来初始化枚举。 如果对象不匹配,则为nil初始化。
Swift基础中的大多数对象都符合RawRepresentable:String,Int,Double等。如果将枚举定义为Int或String,则Swift会创建一个名为Implicitly Assigned的东西,并自动为每种情况添加rawValue。
枚举类型:字符串{
外壳电,火,水,草
}
print(Pokemon.Type.electric.rawValue)//打印电
让 electricTypeFromString = Pokemon.Kind.init(rawValue:“ electric”)
让 nilTypeFromString = Pokemon.Kind.init(rawValue:“⚡️-雷声”)
枚举属性和方法
在Swift枚举中可以具有属性。 这些属性不能存储,但是可以计算。 它们使我们可以获取有关枚举电流值的更多信息。
枚举类型:字符串{
外壳电,火,水,草
///一个大写的字符串
变量名称:字符串{
返回 self .rawValue.capitalized
}
///带有表情符号的字符串将重置当前类型
var emoji:字串{
切换 自我 {
案例 .electric:
返回 “⚡️”
案例 .fire:
返回 “🔥”
案例 .water:
返回 “💧”
案例 .grass:
返回 “🌱”
}
}
///相对于当前类型弱的类型的数组
var优势:[种类] {
切换 自我 {
案例 .electric:
返回 [.fire,.water]
案例 .fire:
返回 [.grass]
案例 .water:
返回 [.fire]
案例 .grass:
返回 [.electric,.water]
}
}
///一个针对当前类型的类型数组
var弱点:[种类] {...}
}
let electricType =宠物小精灵
let waterType =宠物小精灵.kind.water
如果 electricType.strengths.contains(waterType){
//⚡️ 类型又好 good
print(“ \(electricType.emoji)对\(waterType.emoji)有利)
}
Swift还允许我们向枚举添加方法。 这可以为特定的枚举案例提供更多功能。
枚举类型:字符串{
外壳电,火,水,草
///一个大写的字符串
var名称:字符串{...}
///带有表情符号的字符串将重置当前类型
var emoji:字符串{...}
///相对于当前类型弱的类型的数组
var优势:[种类] {...}
///一个针对当前类型的类型数组
var弱点:[种类] {...}
///评估当前类型是否强,再确定口袋妖怪的类型
///
///- 参数 pokemon:将被评估的Pokemon
///- 返回 :如果当前类型为强类型,则返回true
宠物小精灵,否则返回false
func isStrongAgainstPokemon( _ pokemon:Pokemon)->布尔{
返回 自身 .strengths.contains(pokemon.type)
}
}
let waterType =宠物小精灵.kind.water
let pikachu = Pokemon(索引:25,名称:“ Pikachu”,键入:.electric)
打印(waterType.isStrongAgainstPokemon(pikachu))
迭代枚举
如果我们想得到一个枚举的所有情况,可以用一种简单的方式做到。 枚举可以实现协议。 为了获得所有案例的数组,我们可以实现CaseIterable协议。
因此,要获取我们所有的Pokemon类型并对其进行迭代,我们可以执行以下操作:
枚举类型:字符串,CaseIterable {
外壳电,火,水,草
///一个大写的字符串
var名称:字符串{...}
...
}
用于 Pokemon.Kind.allCases中的类型{
打印(type.name)
}
关联价值
使用Swift,可以将特定值存储到案例中。 此值称为关联属性。 这意味着一个案例可以具有与另一个案例不同的属性。
在我们的示例中,我们想要定义口袋妖怪的当前状态。 它可能是狂野的,也可能属于教练员。 如果它属于培训师,我们想知道是哪个培训师。 为了解决这个问题,我们可以使用带有2个case wild和Trainer的Enum 。 我们使用关联的值来将训练器对象匹配到我们的训练器案例。
神奇宝贝类 {
让指数:整数
变量名称:字符串
var类型:种类
var status:状态= .wild
初始化 (索引:整数,名称:字符串,类型:类型){...}
}
培训师类 {
//培训者的名字
var id:字符串
//培训者的名字
变量名称:字符串
初始化 (ID:字符串,名称:字符串){
自我 .id = id
自我 .name =名称
}
}
宠物小精灵扩展名 {
枚举状态{
大小写狂
案例负责人(培训师:培训师)
var isWild:Bool {
切换 自我 {
案例 .wild:
返回 真
默认值 :
返回 假
}
}
}
}
让 eduardoTrainer =培训师(id:“ T1”,名称:“ Eduardo”)
let pikachu = Pokemon(索引:25,名称:“ Pikachu”,键入:.electric)
pikachu.status = .owner(培训师:eduardoTrainer)
如果 pikachu.status.isWild {
打印(“这个家伙很疯狂,抓住它!”)
} 其他 {
打印(“皮卡丘属于某人”)
}
并获得教练名称:
神奇宝贝课程 {
让指数:整数
变量名称:字符串
var类型:种类
var status:状态= .wild
var培训师:培训师? {
切换 self .status {
案例 .wild:
返回 零
案例 .owner( 让培训师):
回程教练
}
}
初始化 (索引:整数,名称:字符串,类型:类型){...}
}
...
打印(pikachu.trainer?.name ??“没有所有者”)
比较枚举
默认情况下,如果枚举具有rawValue,它将用于比较枚举。 这是因为RawRepresentable符合Equatable,Comparable和Hashable协议。
如果我们没有为枚举定义类型并且它具有关联的值,那么我们将无法进行比较。 这些枚举不符合Equatable协议。 不错的是,我们可以添加Equatable协议进行比较。 让我们看一下Pokemon.Status的示例。
扩展名 Pokemon.Status:Equatable {
静态 函数 ==(lhs:Pokemon.Status,rhs:Pokemon.Status)-> Bool {
如果 lhs.isWild && rhs.isWild {
返回 真
}
让 lhsTrainer:培训师? = {
切换 lhs {
案例 .wild:
返回 零
案例 .owner( 让培训师):
回程教练
}
}()
让 rhsTrainer:培训师? = {
切换 rhs {
案例 .wild:
返回 零
案例 .owner( 让培训师):
回程教练
}
}()
返回 lhsTrainer == rhsTrainer
}
}
扩展培训师:平等{
静态 函数 ==(lhs:培训师,rhs:培训师)->布尔{
返回 lhs.id == rhs.id
}
}
让 eduardoTrainer =培训师(id:“ T1”,名称:“ Eduardo”)
let pikachu = Pokemon(索引:25,名称:“ Pikachu”,键入:.electric)
let bulbasaur = Pokemon(索引:1,名称:“ Bulbasaur”,键入:.grass)
pikachu.status = .owner(培训师:eduardoTrainer)
bulbasaur.status = .owner(培训师:eduardoTrainer)
如果 pikachu.status == bulbasaur.status {
打印(“皮卡丘和Bulbasaur的状态相同”)
}
结论
(/ ^▽^)/
你做到了! (或者也许您只是向下滚动以查看评论)。 枚举在Swift中是必不可少的,我鼓励尝试使用它们,并在您的代码中使用它们。
请让我知道您在评论中的想法。
完整的游乐场:https://gist.github.com/eduardo22i/6ca76f8e044ba62eae7f0b356426abc5
苹果的Enum指南:https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html