Рефакторинг структуры как перечисление в Swift - PullRequest
0 голосов
/ 21 сентября 2018

Сегодня кто-то прокомментировал этот код и предположил, что было бы лучше в 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?Моя основная цель - ремонтопригодность.

Ниже приводится то, что я придумал:

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
    }
  }
}

На данный момент я выяснил, как добиться аналогичной функциональности с structи enum.enum кажется гораздо более сложным, если кто-то возвращается, чтобы обновить его, и он более подвержен ошибкам.Пол Хегарти говорит, что строка, которая не потерпит крах, - это строка, которую вы не пишете, а маршрут enum выглядит и кажется громоздким.

Есть ли преимущество в памяти для перехода по маршруту enum по сравнению с struct?

Когда я закончу, я хотел бы иметь возможность передавать Политику в качестве параметра, например, так:

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

test(for: Policy.first)

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Единственное улучшение при использовании перечисления, о котором я могу подумать, - это просто замена ключевого слова 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) { }

не может быть вызвана из вашего кода, так как невозможно создать (выделить) a 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, нет неоднозначного доступа к свойствам (доступ к элементам помеченного кортежа можно получить либо через метку, либо черезуказатель).

0 голосов
/ 21 сентября 2018

Вот такая возможность.Это немного долго, но это Swifty:

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.Недавно я столкнулся с такой же ситуацией, как и вы, и я тоже пытался использовать перечисление вместо структуры.Я даже экспериментировал с именованным кортежем.Но в итоге я использовал структуру.

...