Подтвердить что ты не робот

Быстрые константы: Struct или Enum

Я не уверен, какой из двух лучше определить константы. Строка или перечисление. Структура будет копироваться каждый раз, когда я ее использую или нет? Когда я думаю о структуре с константами static let, нет смысла, что она будет копироваться все время, на мой взгляд. Но если он не будет скопирован, то не имеет значения, что я беру?

Какие преимущества имеет выбор структуры или перечисления?

Франсиско говорит, что используйте Struct.

Рей Вундерлих говорит, что использует Enum's. Но мне не хватает оправдания.

4b9b3361

Ответ 1

Обе структуры и перечисления работают. В качестве примера, оба

struct PhysicalConstants {
    static let speedOfLight = 299_792_458
    // ...
}

и

enum PhysicalConstants {
    static let speedOfLight = 299_792_458
    // ...
}

работать и определять статическое свойство PhysicalConstants.speedOfLight.

Re: Структура будет копироваться каждый раз, когда я ее использую или нет?

Оба struct и enum являются типами значений, которые также относятся к перечислениям. Но это не имеет значения здесь потому что вам не нужно создавать значение вообще: Статические свойства (также называемые свойствами типа) являются свойствами самого типа, а не экземпляром этого типа.

Re: Какие преимущества имеет выбор структуры или перечисления?

Как упоминалось в связанной статье:

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

Итак, для структуры

let foo = PhysicalConstants()

создает (бесполезное) значение типа PhysicalConstants, но для беззаботного перечисления он не скомпилируется:

let foo = PhysicalConstants()
// error: 'PhysicalConstants' cannot be constructed because it has no accessible initializers

Ответ 2

Использование Xcode 7.3.1 и Swift 2.2

В то время как я согласен с Martin R, а руководство по стилю Ray Wenderlich дает хорошее представление о том, что перечисления лучше всего почти во всех случаях использования из-за того, что он является чистым пространством имен, есть одно место, где используется struct trumps enums.

Операторы switch

Начнем с версии struct:

struct StaticVars {
    static let someString = "someString"
}

switch "someString" {
case StaticVars.someString: print("Matched StaticVars.someString")
default: print("Didn't match StaticVars.someString")
}

Используя структуру, это будет соответствовать и распечатать Matched StaticVars.someString.

Теперь рассмотрим версию безразличного enum (только изменив ключевое слово struct на enum):

enum StaticVars {
    static let someString = "someString"
}

switch "someString" {
case StaticVars.someString: print("Matched StaticVars.someString")
default: print("Didn't match StaticVars.someString")
}

Вы заметите, что вы получаете ошибку времени компиляции в инструкции switch в строке case StaticVars.someString:. Ошибка Enum case 'someString' not found in type 'String'.

Существует псевдо-обходное решение путем преобразования статического свойства в закрытие, которое возвращает тип.

Итак, вы изменили бы это так:

enum StaticVars {
    static let someString = { return "someString" }
}

switch "someString" {
case StaticVars.someString(): print("Matched StaticVars.someString")
default: print("Didn't match StaticVars.someString")
}

Обратите внимание на необходимость скобок в аргументе case, потому что теперь это функция.

Недостатком является то, что теперь, когда мы сделали его функцией, он запускается каждый раз при вызове. Так что, если это просто простой примитивный тип типа String или Int, это не так уж плохо. Это, по сути, вычислимое свойство. Если это константа, которую нужно вычислить, и вы хотите ее только вычислить, подумайте о ее вычислении в другое свойство и вернете уже вычисленное значение в закрытии.

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

struct StaticVars {
    static let someString = "someString"
    private init() {}
}

Но при этом вы хотите поместить объявление структуры в свой собственный файл, потому что если вы объявили его в том же файле, что, скажем, класс View Controller, этот файл класса все равно сможет случайно создайте ненужный экземпляр StaticVars, но вне файла класса он будет работать по назначению. Но это ваш звонок.

Ответ 3

Вот короткий ответ: должны ли ваши константы быть уникальными? Затем используйте перечисление, которое обеспечивает это.

Хотите использовать несколько разных констант, чтобы содержать одно и то же значение (часто полезно для ясности)? Затем используйте структуру, которая позволяет это.