Можно ли добавить хранимое свойство (stored property) в расширение (extension) в Swift?

Ответ

Нет, напрямую добавить хранимое свойство (stored property) в расширение (extension) в Swift нельзя. Расширения предназначены для добавления функциональности, а не для хранения состояния.

Что МОЖНО добавить в extension:

  • Вычисляемые свойства (computed properties)
  • Методы
  • Инициализаторы (только convenience)
  • Сабскрипты
  • Вложенные типы

Пример вычисляемого свойства (разрешено):

extension Double {
    var km: Double { return self * 1000.0 } // Вычисляется при каждом обращении
    var cm: Double { return self / 100.0 }
}
let distance = 5.km // 5000.0

Обходные пути для хранения состояния:

1. Ассоциированные объекты (Objective-C runtime) Позволяют привязать значение к объекту, но работает только с классами, наследующими от NSObject.

extension UIView {
    private struct AssociatedKeys {
        static var customIdentifier = "customIdentifier"
    }

    var customIdentifier: String? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.customIdentifier) as? String
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.customIdentifier, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

2. Использование глобальной словарной таблицы (с осторожностью)

private var storedProperties = [ObjectIdentifier: Any]()

extension MyClass {
    var myProperty: Int {
        get { storedProperties[ObjectIdentifier(self)] as? Int ?? 0 }
        set { storedProperties[ObjectIdentifier(self)] = newValue }
    }
}

3. Наследование или композиция (предпочтительный способ)

// Вместо extension, создайте подкласс
class EnhancedView: UIView {
    var customStoredProperty: String = ""
}

// Или используйте композицию
struct ViewWrapper {
    let view: UIView
    var customStoredProperty: String
}

Вывод: Если вам нужно хранить состояние, расширение — неправильный инструмент. Рассмотрите редизайн через подкласс, композицию или (в крайнем случае) ассоциированные объекты.

Ответ 18+ 🔞

А, слушай, вот это классика, блядь! Прямо в точку попал. Сидишь такой, думаешь: «О, расширение — это же круто, сейчас я туда накидаю своих свойств, и будет мне счастье». А нихуя, ёпта!

Нет, нахуй, напрямую воткнуть хранимое свойство (stored property) в расширение (extension) в Swift — нельзя. Вообще, в рот меня чих-пых! Расширения — они как бы для функциональности, чтобы подкрутить, а не для того, чтобы там своё барахло хранить. Это как прийти в гости и начать в шкафу у хозяев свои носки держать — не по понятиям, блядь.

Что МОЖНО в extension впихнуть, не сломав систему:

  • Вычисляемые свойства (computed properties) — они же каждый раз на лету считаются, хуле.
  • Методы всякие.
  • Инициализаторы, но только convenience, чтоб не выёбываться.
  • Сабскрипты.
  • Вложенные типы — ну, там свои enum'ы объявить.

Вот, смотри, пример вычисляемого — это легально:

extension Double {
    var km: Double { return self * 1000.0 } // Каждый раз, сука, пересчитывает, как справку в ЖЭКе
    var cm: Double { return self / 100.0 }
}
let distance = 5.km // 5000.0

А теперь, внимание, ёперный театр! Обходные пути, если прям овердохуища надо хранить своё:

1. Ассоциированные объекты (это из Objective-C runtime, старьё, но работает) Работает только с классами, которые от NSObject пляшут. По сути, привязываем значение к объекту, как жвачку под стол.

extension UIView {
    private struct AssociatedKeys {
        static var customIdentifier = "customIdentifier"
    }

    var customIdentifier: String? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.customIdentifier) as? String
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.customIdentifier, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

2. Глобальная словарная таблица (осторожно, а то сам себя ебнешь)

private var storedProperties = [ObjectIdentifier: Any]()

extension MyClass {
    var myProperty: Int {
        get { storedProperties[ObjectIdentifier(self)] as? Int ?? 0 }
        set { storedProperties[ObjectIdentifier(self)] = newValue }
    }
}

3. Наследование или композиция (нормальный, человеческий путь, блядь!)

// Вместо того, чтобы расширение ебашить, сделай нормальный подкласс
class EnhancedView: UIView {
    var customStoredProperty: String = "" // Вот, пожалуйста, храни на здоровье
}

// Или через композицию — заверни, как подарок
struct ViewWrapper {
    let view: UIView
    var customStoredProperty: String
}

Вывод, сука: Если тебе надо хранить состояние — расширение это не твой инструмент, это как молотком гвозди забивать. Либо делай нормальный подкласс, либо композицию используй, либо, в крайнем случае, эти ассоциированные объекты, если совсем припёрло. Но лучше по-человечески, а то потом сам не разберёшься, что где лежит.