2017-08-04 64 views
2

我想創建一個類,並使用該類作爲我的新枚舉的類型,如下所示。如何在特定類的Swift中聲明枚舉?

class Abc{ 
    var age = 25 
    var name = "Abhi" 
} 

enum TestEnum : Abc { 
    case firstCase 
    case secondCase 
} 

我在操場上出現錯誤。

error: raw type 'Abc' is not expressible by any literal 

所以我試圖符合RawRepresentable這樣的協議。

extension TestEnum : RawRepresentable{ 
    typealias RawValue = Abc 

    init?(rawValue:RawValue) { 
     switch rawValue { 
     case Abc.age : 
      self = .firstCase 

     case Abc.name : 
      self = .secondCase 
     } 
    } 

    var rawValue : RawValue { 
     switch self{ 

     case .firstCase : 
      return Abc.age 

     case .secondCase : 
      return Abc.name 
     } 
    } 
} 

我正在這之後以下錯誤:

error: raw type 'Abc' is not expressible by any literal 
error: instance member 'age' cannot be used on type 'Abc' 
error: instance member 'name' cannot be used on type 'Abc' 

什麼是定義類類型的枚舉,沒有得到明確這一點,思想的正確方法。任何人幫助?

+0

'enum'是一個值類型,而'class'是一個引用類型,所以我不認爲這是可能的。 – Lawliet

+2

你想達到什麼目的? –

+0

從文檔:*「原始值可以是字符串,字符或任何整數或浮點數類型」* –

回答

6

從文檔

特別地,原始值類型必須符合Equatable 協議和以下協議之一: ExpressibleByIntegerLiteral爲整數常量, ExpressibleByFloatLiteral浮點文字, ExpressibleByStringLiteral對於包含字符的任何數字 的字符串文字,以及對於 僅包含單個字符的字符串文字,ExpressibleByUnicodeScalarLiteral或 ExpressibleByExtendedGraphemeClusterLiteral。

所以讓你的班級ABC符合Equatable和上述協議之一。下面是一個例子

public class Abc : Equatable,ExpressibleByStringLiteral{ 
    var age = 25 
    var name = "Abhi" 
    public static func == (lhs: Abc, rhs: Abc) -> Bool { 
     return (lhs.age == rhs.age && lhs.name == rhs.name) 
    } 
    public required init(stringLiteral value: String) { 
     let components = value.components(separatedBy: ",") 
     if components.count == 2 { 
      self.name = components[0] 
      if let age = Int(components[1]) { 
       self.age = age 
      } 
     } 
    } 
    public required convenience init(unicodeScalarLiteral value: String) { 
     self.init(stringLiteral: value) 
    } 
    public required convenience init(extendedGraphemeClusterLiteral value: String) { 
     self.init(stringLiteral: value) 
    } 
} 

enum TestEnum : Abc { 
    case firstCase = "Jack,29" 
    case secondCase = "Jill,26" 
} 

現在就可以初始化你枚舉像

let exEnum = TestEnum.firstCase 
print(exEnum.rawValue.name) // prints Jack 
+0

我對此並不清楚。你能在代碼中解釋嗎? – iPhoneDeveloper

+0

在代碼上工作。等一下。 –

+0

如何從枚舉中獲取名稱? – twealm

4

我真的不知道你想實現什麼,但看看我的實現,辦法,我用在我的項目中:

class Abc { 
    var age: Int 
    var name: String 

    init(age: Int, name: String) { 
     self.age = age 
     self.name = name 
    } 
} 


enum TestEnum { 
    case firstCase 
    case secondCase 

    var instance: Abc { 
     switch self { 
     case .firstCase: return Abc(age: 25, name: "John") 
     case .secondCase: return Abc(age: 20, name: "Marry") 
     } 
    } 
} 

//Usage: 

let abc = TestEnum.secondCase.instance 
print(abc.age) //prints '20' 
+0

我們可以像這樣聲明枚舉,枚舉SomeEnum:Int {}或枚舉SomeEnum:String {}。爲什麼不喜歡這個枚舉SomeEnum:SomeClass {}? – iPhoneDeveloper

+0

回答iPhoneDeveloper的問題:因爲枚舉的每個實例都必須歸結爲String或Int。 Mohamemed的上面的答案解釋了一種複雜的方式來執行像您所說的聲明,並且仍然使每個枚舉符合這些規則。但是,爲了代碼可讀性,我更喜歡Michal的答案。它的工作原理。 – ClayJ

1

看看Associated Values。 對於示例:

class Abc { 
    var age = 25 
    var name = "Abhi" 
} 

enum TestEnum { 
    case age(Int) 
    case name(String) 
} 

然後你可以使用它像這樣:

var person = Abc() 
... 
var value = TestEnum.age(person.age) 

switch value { 
    case .age(let age): 
     print("Age: \(age).") 
    case .name(let name): 
     print("Name: \(name).") 
} 

爲方便起見,你可以寫擴展枚舉,將您Abc對象,並將其轉換爲枚舉值:

static func fromAbc(_ object: Abc) -> TestEnum? { 
    if object.age { 
     return TestEnum.age(object.age) 
    } 

    if object.name { 
     return TestEnum.name(object.name) 
    } 

    return nil 
} 

注意:func fromAbc(object: Abc) -> TestEnum?你應該在如果的更換條件的東西,可以表示爲布爾(age > 0等)。

至於行值 - 在doc中指出,

原始值可以是字符串,字符或任何整數或浮點數類型。每個原始值在其枚舉聲明中必須是唯一的。

而且我不確定你可以在那裏適應課堂。

+0

你可以。看到我的答案。 –

+0

@twealm感謝您的答覆和澄清。 – iPhoneDeveloper