【问题标题】:Advanced Java enums in SwiftSwift 中的高级 Java 枚举
【发布时间】:2015-07-01 09:08:20
【问题描述】:

我有许多需要转换为 Swift 代码的 Java 类。 其中一个类有一个高级枚举:

public enum Student {

  STUDENT_ONE("Steve", "Jobs")
  STUDENT_TWO("Tim", "Cook")

  private String _firstName;
  private String _lastName;
}

如何在 Swift 中复制相同的行为?

【问题讨论】:

    标签: java ios swift enums


    【解决方案1】:

    经过一番思考,我同意 godmoney 的观点,即 aksh1t 的解决方案比我使用字符串的解决方案更好。

    无论如何,这是 aksh1t 解决方案的更简洁的变体,仅使用一个返回元组的计算属性:(在 Swift 2.0 中测试)

    enum Student {
        case STUDENT_ONE, STUDENT_TWO
    
        typealias Details = (firstName: String, lastName: String)
        var details : Details {
            switch(self) {
            case STUDENT_ONE : return ("Steve", "Jobs")
            case STUDENT_TWO : return ("Tim", "Cook")
            }
        }
    }
    
    // Usage:
    func test(sd: Student.Details) {
        print(sd.firstName)
        print(sd.lastName)
    }
    test(Student.STUDENT_ONE.details)
    

    【讨论】:

      【解决方案2】:

      我试图将 Java 代码转换为 Swift 做同样的事情,但最终做了这样的事情:

      public enum Student {
      
          case STUDENT_ONE
          case STUDENT_TWO
      
          var firstName: String {
              get {
                  switch self {
                  case .STUDENT_ONE:
                      return "Steve"
                  case .STUDENT_TWO:
                      return "Tim"
                  }
              }
          }
      
          var lastName: String {
              get {
                  switch self {
                  case .STUDENT_ONE:
                      return "Jobs"
                  case .STUDENT_TWO:
                      return "Cook"
                  }
              }
          }
      }
      

      现在,这真的很长而且很混乱,我不确定这是否是正确的方法,但我找不到其他任何有效的方法。我很想知道是否有其他更好的方法。

      【讨论】:

      • 我添加了我目前处理它的方式。不确定我更喜欢这两种解决方案中的哪一种......
      • 这太复杂了,太冗长了。
      【解决方案3】:

      这就是我最终要做的——完全不确定:

      struct Students {
      
          enum Students {
              case STUDENT_ONE(String, String)
              case STUDENT_TWO(String, String)
          }
      
          let STUDENT_ONE = Students.STUDENT_ONE("Steve", "Jobs")
          let STUDENT_TWO = Students.STUDENT_TWO("Steve", "Two")
      }
      

      【讨论】:

      • 这绝对比我的答案更好(或者我应该说的不那么冗长)。
      • 仍然不确定这个解决方案。在我接受这个作为答案之前,我希望能看到一些其他的建议。
      【解决方案4】:

      枚举不一定是表示此类数据的最佳选择。我选择了structs,使用正确的访问器效果很好:

      public struct Student {
          public let firstName : String
          public let lastName : String
      
          public static let STUDENT_ONE = Student(firstName: "Steve", lastName: "Jobs")
          public static let STUDENT_TWO = Student(firstName: "Tim", lastName: "Cook")
      }
      

      【讨论】:

      • 你甚至可以省略init方法而使用默认构造函数。
      【解决方案5】:

      从另一个标记为重复的问题移至此处,因此变量名称不完全匹配,但是,概念都匹配。

      最明显的方法是:

      public enum EnumWeapon {
          case WOODEN_SWORD
          case STONE_SWORD
          case STEEL_SWORD
      
          func getName() -> String {
              switch self {
              case WOODEN_SWORD:  return "Wooden Sword"
              case STONE_SWORD:   return "Stone Sword"
              case STEEL_SWORD:   return "Steel Sword"
              }
          }
      
          func getDamage() -> Int {
              switch self {
              case WOODEN_SWORD:  return 4
              case STONE_SWORD:   return 6
              case STEEL_SWORD:   return 8
              }
          }
      }
      

      如果你有一个值与每个枚举案例相关联,你可以使用原始值语法,或者只是使用它来简化上面的枚举案例:

      public enum Weapon : Int {
          case WOODEN_SWORD = 4
          case STONE_SWORD = 6
          case STEEL_SWORD = 8
      
          func getDamage() -> Int {
              return rawValue
          }
      
          func getName() -> String {
              switch self {
              case .WOODEN_SWORD: return "Wooden Sword"
              case .STONE_SWORD:  return "Stone Sword"
              case .STEEL_SWORD:  return "Steel Sword"
              }
          }
      }
      

      显然,如果不需要名称,可以省略getName 函数。同样,您可以省略 getDamage 函数而只使用 weapon.rawValue

      一种更简单但更类似于实际 Java 实现的方法是使用结构而不是枚举,如下所示:

      public struct Weapon {
          public let name : String
          public let damage : Int
      
          private init(name:String, damage:Int) {
              self.name = name
              self.damage = damage
          }
      
          public static let WOODEN_SWORD = Weapon(name: "Wooden Sword", damage: 4)
          public static let STONE_SWORD = Weapon(name: "Stone Sword", damage: 6)
          public static let STEEL_SWORD = Weapon(name: "Steel Sword", damage: 8)
      }
      

      并且,重新定义运算符 ==,您可以获得相等比较:

      func == (lhs:Weapon, rhs:Weapon) -> Bool {
          return lhs.name == rhs.name && lhs.damage == rhs.damage
      }
      

      并且,通过重新定义运算符 ~= 您可以让 switch 按预期工作:

      func ~= (lhs:Weapon, rhs:Weapon) -> Bool {
          return lhs == rhs
      }
      
      func test(sword:Weapon) {
          switch sword {
          case Weapon.STONE_SWORD:    print("stone")
          default:                    print("something else")
          }
      }
      
      test(Weapon.STONE_SWORD)
      

      很多选项,主要取决于您真正想要做什么以及需要在枚举中包含多少数据。

      【讨论】:

        猜你喜欢
        • 2010-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-19
        • 1970-01-01
        • 1970-01-01
        • 2021-05-07
        相关资源
        最近更新 更多