Swift - 将同一变量的不同枚举类型传递给类

时间:2017-07-26 06:53:50

标签: swift enums

如何将不同的枚举类型传递给同一个变量,稍后识别其类型并使用其原始值来执行某些操作?

我有两个类型为String的枚举Menu1Menu2。我喜欢将一系列枚举传递给另一个显示子菜单的类。我喜欢将枚举传递给同一个变量,因为我将来可能会添加另一个菜单。

4 个答案:

答案 0 :(得分:2)

要应用抽象,您可以使用 protocol ,如下所示:

protocol Menu {}

enum Menu1: String, Menu {
    case option1 = "Option 01 From Menu 01"
    case option2 = "Option 02 From Menu 01"
    case option3 = "Option 03 From Menu 01"
    case option4 = "Option 04 From Menu 01"
    case option5 = "Option 05 From Menu 01"
}

enum Menu2: String, Menu {
    case option1 = "Option 01 From Menu 02"
    case option2 = "Option 02 From Menu 02"
    case option3 = "Option 03 From Menu 02"
    case option4 = "Option 04 From Menu 02"
    case option5 = "Option 05 From Menu 02"
}

通过实现这一点,您可以声明Menu类型的数组,其中包含两个枚举:

let myMenu1Array: [Menu1] = [.option1, .option2, .option5]
let myMenu2Array: [Menu2] = [.option1, .option3, .option4]

例如,将参数作为Menu的数组的函数应该起作用:

func handleMenu(_ menuArray: [Menu]) {
    if let menu1Array = menuArray as? [Menu1] {
        print("Menu 1 Detected!")

        // you could iterate through it for instance...
        for option in menu1Array {
            print(option.rawValue)
        }

        return
    }

    if let menu2Array = menuArray as? [Menu2] {
        print("Menu 2 Detected!")

        // you could iterate through it for instance...
        for option in menu2Array {
            print(option.rawValue)
        }

        return
    }
}

输出结果为:

handleMenu(myMenu1Array)
/*
 Menu 1 Detected!
 Option 01 From Menu 01
 Option 02 From Menu 01
 Option 05 From Menu 01
 */

handleMenu(myMenu2Array)
/*
 Menu 2 Detected!
 Option 01 From Menu 02
 Option 03 From Menu 02
 Option 04 From Menu 02
 */

因此,如果某个类中的属性应该代表一个菜单,则可以将其声明为Menu的类型:

class  MyClass {
    ...

    var menu: Menu?

    ...
}

答案 1 :(得分:1)

您可以声明一个协议,两个枚举应该符合。 现在接受确认协议的函数参数。或者,您可以使用泛型。

答案 2 :(得分:1)

您需要一种方法来连接两个枚举,这可能是一个常见的Menu协议。你将面临的问题是传递Menu对象所涉及的类型擦除。添加新的菜单类型太容易了,而不是在代码中的任何地方检查它。

我建议使用一个小型重构器,将每个重构器包装到另一个枚举器中,由一个共同的结构管理。

enum Menu1: String {
    case option1 = "Option 01 From Menu 01"
    case option2 = "Option 02 From Menu 01"
    case option3 = "Option 03 From Menu 01"
    case option4 = "Option 04 From Menu 01"
    case option5 = "Option 05 From Menu 01"
}

enum Menu2: String {
    case option1 = "Option 01 From Menu 02"
    case option2 = "Option 02 From Menu 02"
    case option3 = "Option 03 From Menu 02"
    case option4 = "Option 04 From Menu 02"
    case option5 = "Option 05 From Menu 02"
}

struct Menu
{
    enum MenuType
    {
        case one (Menu1)
        case two (Menu2)
    }

    let type: MenuType
}


func handle(menu: Menu)
{
    switch menu.type
    {
    case .one(let data): print (data.rawValue)
    case .two(let data): print (data.rawValue)
    }
}

let menu = Menu(type: .one(Menu1.option1))
handle(menu: menu)

这种方法的主要优点:

  1. 您可以随意添加菜单
  2. 每当您添加新的菜单类型时,代码中的所有switch语句都会出现编译时错误,显示您需要更新代码的位置
  3. 新菜单的关联数据类型可以是任何内容(结构,图像,嵌套子菜单等)
  4. 没有选项 - 只有具体类型

答案 3 :(得分:0)

<块引用>

我们可以使用协议发送任何枚举对象,无需输入 强制转换对象以访问 rawValue。我们可以通过不同类型的 枚举并读取值。

protocol AttributeKeyProtocol {
    var value: String { get }
}

struct AttributeData {
     let key: AttributeKeyProtocol
     let value: String
     init(key: AttributeKeyProtocol, value: String) {
        self.key = key
        self.value = value
    }
}

enum MyClasses: AttributeKeyProtocol {
    var value: String {
        switch self {
        case .one(.logo):
            return"logo"
        default:
            return "all"
        }
    }
    
    case one(MyComputerClasses)
    case two
    
    enum MyComputerClasses: String, AttributeKeyProtocol {
        case logo
        case pascal
        
        var value: String {
            return self.rawValue
        }
    }
}

MyClasses implementing 'AttributeKeyProtocol'


enum MyCourses: String, AttributeKeyProtocol {
    case three = "psd_ssj_sdoj"
    case four
    
    var value: String {
        return self.rawValue
    }
}

class NewSDK {
    func track(name: String, type: String, attributes: [AttributeData]?) {
        print("attributes:  \(attributes?.first?.key.value)")
        print("attributes:  \(attributes?.last?.key.value)")
    }
}

NewSDK().track(name: "sfd", type: "dsfd", attributes: [.init(key: MyClasses.one(.logo) , value: "sdfd"),
                                                         .init(key: MyCourses.three, value: "sfdfsd")])