Reputation: 1206
How can I pass different enums types to a same variable, identify its type later and use its raw values to do some operations?
I have two enums Menu1
and Menu2
of type String. I like to pass an array of enums to another class which shows submenu. I like to pass enum to same variable since I may add another menu in future.
Upvotes: 3
Views: 2753
Reputation: 433
We can use protocol and send any enum object and no need to type cast the object to access the rawValue. we can pass different types of enums and read the values.
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")])
Upvotes: 0
Reputation: 31645
For applying abstraction, you could use protocol
, as follows:
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"
}
By implementing this, you are able to declare arrays of Menu
type, which include both of the enums:
let myMenu1Array: [Menu1] = [.option1, .option2, .option5]
let myMenu2Array: [Menu2] = [.option1, .option3, .option4]
For instance, a function that takes a parameter as array of Menu
s should work:
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
}
}
The output would be:
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
*/
So, if you have a property in a class that should represents a menu, you could declare it as a type of Menu
:
class MyClass {
...
var menu: Menu?
...
}
Upvotes: 2
Reputation: 1509
You need a way to connect the two enums, which could be a common Menu
protocol. The problem you'll face there is the type erasure involved in passing the Menu
object around. It's far too easy to add a new menu type, and not check for it everywhere in your code.
I suggest a small refactor, wrapping each into a another enum, managed by a common struct.
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)
The key advantages to this method:
Upvotes: 1
Reputation: 5241
You can declare one protocol, that the two enums should conform to. Now accept in your function parameter that confirms to the protocol. Alternatively you can make use of generics.
Upvotes: 1