Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift enums with stored fields?

Tags:

enums

swift

So, I’ve been looking for a solution to this problem for about 2 days. I’ve rummaged the Swift documentation, tried many different google / stack overflow searches, and just straight up randomly wrote code to no avail. I think part of the problem is that I don’t know how to word it... so sorry is this is confusing, but hopefully the code I attached clears it up.

Anyways, I want to know if it’s possible to have a private field in an enum such that each enum value has its own value for this field. I am not asking about extending another class, and I’m not asking about associated values. Unfortunately, I have yet to come across anything online saying whether this is allowed in Swift, and so, how to do it. To highlight my question, I’m trying to recreate the following Java code in Swift:

// Java

public enum Direction {

  LEFT(0, -1), RIGHT(0, 1), UP(-1, 0), DOWN(1, 0);

  private final int rowChange, colChange;

  Direction(int rowChange, int colChange) {
    this.rowChange = rowChange;
    this.colChange = colChange;
  }

  public int rowChange() {
    return this.rowChange;
  }

  public int colChange() {
    return this.colChange;
  }

}

This is what I have at the moment, which works, but I would rather have it have stored values rather than switching through each possible case.

// Swift

public enum Direction {

  case left, right, up, down

  public func rowChange() -> Int {
    switch self {
    case .left:
      return 0
    case .right:
      return 0
    case .up:
      return -1
    case .down:
      return 1
    }
  }

  public func colChange() -> Int {
    switch self {
    case .left:
      return -1
    case .right:
      return 1
    case .up:
      return 0
    case .down:
      return 0
    }
  }

}
like image 383
user11591069 Avatar asked Oct 30 '25 16:10

user11591069


2 Answers

You can conform to RawRepresentable and use (Int, Int) as Self.RawValue:

enum Direction : RawRepresentable {
    case left, right, up, down

    var rawValue : (Int, Int) {
        switch self {
        case .left: return (0, -1)
        case .right: return (0, 1)
        case .up: return (-1, 0)
        case .down: return (1, 0)
        }
    }

    init?(rawValue: (Int, Int)) {
        switch rawValue {
        case (0, -1): self = .left
        case (0, 1): self = .right
        case (-1, 0): self = .up
        case (1, 0): self = .down
        case (_, _): return nil
        }
    }

    var rowChange : Int { return self.rawValue.0 }
    var colChange : Int { return self.rawValue.1 }
}

Then you could use it like this:

print(Direction.left.rawValue) // --> (0, -1)
print(Direction.left.rowChange) // --> 0
print(Direction.left.colChange) // --> -1
like image 77
LoVo Avatar answered Nov 01 '25 12:11

LoVo


Switching on self is the standard way. You can have a single value assigned to a enum by letting it inherit from Int (or String is another common case). But for two values like this, the switch would be the normal way.

Maybe consider using a struct instead? Something like this:

struct Direction: Equatable {

    let row: Int
    let column: Int

    static let left = Direction(row: 0, column: -1)
    static let right = Direction(row: 0, column: 1)
    static let up = Direction(row: -1, column: 0)
    static let down = Direction(row: 1, column: 0)

    private init() { 
        // Just to disable empty initialisation, not actually used.
        self.row = 0
        self.column = 0
    }

    private init(row: Int, column: Int) {
        self.row = row
        self.column = column
    }
}

And it can be accessed like this:

let direction = Direction.left
let row = direction.row
let column = direction.column

Also, if the goal is to use pattern matching, it's possible when the struct inherits from Equatable allowing you to write something like:

switch direction {
case .left:
    break
case .right:
    break
case .up:
    break
case .down:
    break
default:
    break
}
like image 34
Claus Jørgensen Avatar answered Nov 01 '25 10:11

Claus Jørgensen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!