Объявляйте тип Swift таким же, как атрибут экземпляра

#swift

#swift

Вопрос:

Например, функция вернет значение типа T , такого же, как у атрибута экземпляра, следующим образом:

 // how to write the type T
func executeTask() -> T {
  // build and run a task
  let task = Process()
  ...
  task.launch()

  let status: T = task.terminationStatus
  return status
}
 

-[Process terminationStatus] возвращает Int32 значение в Swift, но однажды тип может измениться.

Вместо определения явного возвращаемого типа, например func executeTask() -> Int32 {...} , есть ли лучший способ определить возвращаемый тип всегда таким же, как атрибут экземпляра?

Комментарии:

1. Если возвращаемый тип terminationStatus изменяется, у вас возникают более серьезные проблемы, о которых нужно беспокоиться, чем изменение возвращаемого типа executeTask , а именно, что весь ваш код, который зависит от executeTask возврата an Int32 , сломается.

2. Что такое «атрибут экземпляра»? Что означает «всегда совпадает с атрибутом экземпляра»? И что этот код пытается сделать? Использование T предполагает универсальную, но это не универсальная функция, поэтому это не имеет смысла.

Ответ №1:

Я бы подумал о добавлении явного пользовательского типа для возвращаемого значения таким образом, чтобы его расширением можно было управлять и не затрагивать уже существующий код.

Вот пример использования enum

 enum TaskStatus {
    case code(Int)
    // case value(String)   // << ex. add in future
}

func executeTask() -> TaskStatus {
  // build and run a task
  let task = Process()
  //...
  task.launch()

  let status = task.terminationStatus
  return .code(status)
}
 

Комментарии:

1. Enum Здесь лучше, чем typealias ?

2. Изменение типов повлияет на существующий код (ошибки компиляции, приведение, логика и т. Д.), Добавление нового регистра в enum не повлияет. Поэтому я бы сказал, что да, это более уместно.

Ответ №2:

Может быть другой подход, который, по крайней мере, поможет вам не нарушать ваш код, когда вы решите изменить возвращаемый тип.

Вы можете объявить специальный класс для статуса задачи, состоящий из всех форматов, которые вам нужны или понадобятся в будущем. Вы также можете создать инициализатор, который будет приносить Any значение и преобразовывать его во все нужные вам типы. Вот так:

 class TaskStatus {

    var int32status: Int32?
    
    init(with value: Any) {
        switch value {
        case is Int32:
            int32status = value
        case is Int:
            int32status = Int32(value)
        default:
            print("Task Status initialization for type (String(describing: value)) is not prepared")
        }
    }
}
 

И в вашем коде:

 func executeTask() -> TaskStatus {
  // build and run a task
  let task = Process()
  ...
  task.launch()

  let status: T = task.terminationStatus
    
  return TaskStatus(with: status)
}