在Swift中将struct重构为枚举

时间:2018-09-21 01:14:02

标签: ios swift struct enums

今天有人评论了此代码,并建议在enum中使用它会更好:

typealias PolicyType = (filename: String, text: String)

struct Policy {
  static let first = PolicyType(filename: "firstFile.txt", text: "text in first file")
  static let second = PolicyType(filename: "secondFile.txt", text: "text in second file")
  static let third = PolicyType(filename: "thirdFile.txt", text: "text in third file")
}

let thirdPolicyText = Policy.third.text

使用枚举是否有更有效的内存且更易于维护?我的主要目标是可维护性。

以下是我想出的内容:

enum Policy: RawRepresentable {
  case one
  case two
  case three

  var rawValue: (filename: String, text: String) {
    switch self {
    case .one:
      return ("1", "policy 1 text")
    case .two:
      return ("2", "policy 2 text")
    case .three:
      return ("3", "policy 3 text")
    }
  }

  init?(rawValue: (filename: String, text: String)) {
    switch rawValue {
    case ("1", "policy 1 text"):
      self = .one
    case ("2", "policy 2 text"):
      self = .two
    case ("3", "policy 3 text"):
      self = .three
    default:
      return nil
    }
  }
}

至此,我已经弄清楚了如何使用structenum实现类似的功能。如果有人返回进行更新,enum似乎需要更多维护,并且更容易出错。保罗·黑格蒂(Paul Hegarty)表示,不会崩溃的行就是您不写的行,并且enum路线看上去和感觉都很麻烦。

enum相比,struct路由有存储优势吗?

完成后,我希望能够将Policy作为参数传递出去,像这样:

func test(for policy: Policy) {
  print(policy.rawValue.filename)
  print(policy.rawValue.text)
}

test(for: Policy.first)

2 个答案:

答案 0 :(得分:3)

有可能。有点长,但是很迅速:

enum Policy {
    case one, two, three

    var filename: String {
        switch self {
        case .one: return "Policy 1 name"
        case .two: return "Policy 2 name"
        case .three: return "Policy 3 name"
        }
    }

    var text: String {
        switch self {
        case .one: return "Policy 1 text"
        case .two: return "Policy 2 text"
        case .three: return "Policy 3 text"
        }
    }
}

目前,Swift枚举的问题在于它们仅限于RawValues。我最近遇到了与您类似的情况,并且我也尝试使用枚举而不是结构。我什至尝试了一个命名元组。但是,我最终使用了一个结构。

答案 1 :(得分:1)

使用我能想到的枚举的唯一改进就是将struct关键字简单地替换为enum

enum Policy {
  static let first = PolicyType(filename: "firstFile.txt", text: "text in first file")
  static let second = PolicyType(filename: "secondFile.txt", text: "text in second file")
  static let third = PolicyType(filename: "thirdFile.txt", text: "text in third file")
}

没有实例的枚举是无法实例化的,因此开发人员只能使用定义的静态策略类型。

像这样的功能:

func cantBeCalled(policy: Policy) { }

由于无法构造(分配)Policy,因此无法从代码中调用。

仍然,我将保留该结构,并将所有内容重新设计为一个类型:

struct Policy {
    static let first = Policy(filename: "firstFile.txt", text: "text in first file")
    static let second = Policy(filename: "secondFile.txt", text: "text in second file")
    static let third = Policy(filename: "thirdFile.txt", text: "text in third file")

    public let filename: String
    public let text: String

    private init(filename: String, text: String) {
        self.filename = filename
        self.text = text
    }
}

结构需要在问题域上更好地映射,因为您需要一个容纳两个属性的容器。当细节数量增加时,元组不善于缩放,并且也很难操作(例如,它们不符合协议)。

此新结构设计具有与上述枚举相同的优点:不能“手动”构造策略,只有一组预定义的策略可用。并带来更多好处:只有一种类型,容器的语义更好,能够使用Policy类型的协议,对属性没有歧义的访问(可以通过标签访问带标签的元组的成员,或通过索引)。