2

Using enums for constants seems to be a simple and elegant solution. Is there a way I can achieve a nested string output using enums?

For example, consider I have the following piece of code:

enum Const {
    enum Car {
        static let Door = "Door"
        static let Engine = "Engine"
    }
}

Is there anyway that I can get "Car| Door" as an output for Const.Car.Door? or "Car| Engine" as output for Const.Car.Engine? and "Car" as output for Const.Car?. I have some analytics constants defined in my current project similar to namespace pattern. It has a LOT of nested tracking events and would really help if I can achieve what I just described above.

What I require:

Const.Car should give the output "Car"

Const.Car.Door should give the output "Car| Door"

Const.Car.Engine should give the output "Car| Engine"

I have no idea on how to achieve that.

EDIT:

This should be also be extendable,

For example,

Const.Car.Door.Handle should give the output "Car| Door| Handle"

Const.Plane should give the output "Plane"

Const.Plane.Flaps should give the output "Plane| Flaps"

3
  • Const.Car cannot be both a string and an enum (in Const.Car.Door) Commented Aug 21, 2017 at 11:18
  • 1
    Yes, I understand that. But forget about enums, is there anyway that we can achieve this? It would make my code feel more structured. Commented Aug 21, 2017 at 11:19
  • 1
    Put differently: If Const.Car == "Car" then Const.Car.Door is invalid. Commented Aug 21, 2017 at 11:22

4 Answers 4

3

Operator overloading may help you to achieve similar functionality. Please look at my solution, you can extend it a lot more

enum Vehicle: String {
    case car = "Car"
    case airplane = "Airplane"

    enum CarPart: String {
        case door = "Door"
        case window = "Window"
    }
}

func > (left: Vehicle, right: Vehicle.CarPart) -> String {
    return left.rawValue + right.rawValue
}


let string = .car > .window // "CarWindow"
Sign up to request clarification or add additional context in comments.

1 Comment

But seems to me that having enums hierarchy more than 2 layers in depth may be more problematic. Operator overloading in such case can be achieved but may be difficult to implement. I personally would prefer @j-caicedo solution
1

I had a time ago a similar problem which I managed to solve using struct and enum. In your case it would look like this:

struct Const{
   enum Car: String {
      case Door = "CarDoor"
      case Engine = "CarEngine"
   }
}

print("\(Const.Car.Door)") //CarDoor
print("\(Const.Car.Engine)") //CarEngine

I hope it fits you well.

Comments

1

This doesn't exactly fulfil your requirements as it doesn't print "Car" when calling Const.Car but it may be somewhere for you to start:

enum Const {
    enum Car {
        static let identifier = "Car"
        static let Door = "\(Car.identifier)Door"
        static let Engine = "\(Car.identifier)Engine"
    }
}

print(Const.Car.Door) //CarDoor
print(Const.Car.Engine) //CarEngine

You can print "Car" by calling Const.Car.identifier though.

Comments

1

Cleanest way I can think of is:

struct Const
{
    enum Car: String, CustomStringConvertible
    {
        case Door
        case Engine

        var description: String
        {
            return "Car\(self.rawValue)"
        }
    }
}

print("\(Const.Car.Door)")    // CarDoor
print("\(Const.Car.Engine)")  // CarEngine

Achieves what you need, makes it really easy to add new cases/parts without any boilerplate, and it would be simple to abstract away this functionality if you wish to support more vehicles.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.