Доступ к значению ассоциации Enumeration в Swift
В этом коде я написал действительно бесполезное перечисление, которое определяет возможный Number
с Int или Float.
Я не могу понять, как я могу получить доступ к значению, которое я установил с помощью ассоциации. Если я попытаюсь распечатать его, я получаю только (Enum Value)
enum Number {
case int (Int)
case float (Float)
}
let integer = Number.int(10)
let float = Number.float(10.5)
println("integer is \(integer)")
println("float is \(float)")
Ответы
Ответ 1
Значение связано с экземпляром перечисления. Поэтому, чтобы получить доступ к нему без коммутатора, вам нужно сделать getter и сделать его доступным явно. Что-то вроде ниже:
enum Number {
case int(Int)
case float(Float)
func get() -> NSNumber {
switch self {
case .int(let num):
return num
case .float(let num):
return num
}
}
}
var vInteger = Number.int(10)
var vFloat = Number.float(10.5)
println(vInteger.get())
println(vFloat.get())
Возможно, в будущем что-то подобное может быть автоматически создано или более короткое удобство может быть добавлено к языку.
Ответ 2
Для полноты, значение ассоциации enum можно было бы также использовать, используя оператор if с сопоставлением с образцом. Вот решение для исходного кода:
enum Number {
case int (Int)
case float (Float)
}
let integer = Number.int(10)
let float = Number.float(10.5)
if case let .int(i) = integer {
print("integer is \(i)")
}
if case let .float(f) = float {
print("float is \(f)")
}
Это решение подробно описано в: https://appventure.me/2015/10/17/advanced-practical-enum-examples/
Ответ 3
Меня удивляет, что Swift 2 (начиная с бета-версии 2) не рассматривает это. Ниже приведен пример обходного подхода:
enum TestAssociatedValue {
case One(Int)
case Two(String)
case Three(AnyObject)
func associatedValue() -> Any {
switch self {
case .One(let value):
return value
case .Two(let value):
return value
case .Three(let value):
return value
}
}
}
let one = TestAssociatedValue.One(1)
let oneValue = one.associatedValue() // 1
let two = TestAssociatedValue.Two("two")
let twoValue = two.associatedValue() // two
class ThreeClass {
let someValue = "Hello world!"
}
let three = TestMixed.Three(ThreeClass())
let threeValue = three. associatedValue() as! ThreeClass
print(threeValue.someValue)
Если ваше перечисление смешивает случаи со связанными значениями и без них, вам нужно сделать тип возврата необязательным. Вы также можете возвращать литералы для некоторых случаев (которые не имеют связанных значений), имитируя типизированные перечисления с необработанным значением. И вы даже можете вернуть значение enum для несвязанных, не-сырых типов. Например:
enum TestMixed {
case One(Int)
case Two(String)
case Three(AnyObject)
case Four
case Five
func value() -> Any? {
switch self {
case .One(let value):
return value
case .Two(let value):
return value
case .Three(let value):
return value
case .Four:
return 4
case .Five:
return TestMixed.Five
}
}
}
let one = TestMixed.One(1)
let oneValue = one.value() // 1
let two = TestMixed.Two("two")
let twoValue = two.value() // two
class ThreeClass {
let someValue = "Hello world!"
}
let three = TestMixed.Three(ThreeClass())
let threeValue = three.value() as! ThreeClass
print(threeValue.someValue)
let four = TestMixed.Four
let fourValue = four.value() // 4
let five = TestMixed.Five
let fiveValue = five.value() as! TestMixed
switch fiveValue {
case TestMixed.Five:
print("It is")
default:
print("It not")
}
// Prints "It is"
Ответ 4
Я использовал что-то вроде этого:
switch number {
case .int(let n):
println("integer is \(n)")
case .float(let n):
println("float is \(n)")
}
Ответ 5
как @iQ. ответ, вы можете использовать свойство в перечислении также
enum Number {
case int (Int)
var value: Int {
switch self {
case .int(let value):
return value
}
}
}
let integer = Number.int(10)
println("integer is \(integer.value)")
Ответ 6
Если вы используете охрану, вы можете написать, как показано ниже:
enum Action {
case .moveTab(index: Int)
}
guard let case .moveTab(index) = someAction else { return }