Ответ
Расширения в Swift предназначены для добавления новой функциональности существующим типам, но не могут добавлять stored properties. Это ограничение связано с тем, что stored properties требуют выделения дополнительной памяти в структуре экземпляра, а расширения не могут изменять макет памяти существующего типа после его компиляции.
Почему это важно?
- Безопасность и предсказуемость: Гарантирует, что расширение не нарушит работу существующего кода, изменив размер или расположение типа в памяти.
- Производительность: Value-типы (структуры, перечисления) копируются по значению. Добавление stored property через расширение потребовало бы создания новой, несовместимой версии типа.
Альтернативы для хранения данных:
- Вычисляемые свойства (Computed Properties):
extension UIView { var cornerRadius: CGFloat { get { layer.cornerRadius } set { layer.cornerRadius = newValue } } } - Ассоциированные объекты (Associated Objects): Работает только для классов, наследующихся от
NSObject. Использует Objective-C runtime.import ObjectiveC
extension UIView { private enum AssociatedKeys { static var customTag = "customTag" }
var customTag: String? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.customTag) as? String
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.customTag, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
3. **Протоколы с реализацией по умолчанию:** Для добавления поведения, а не состояния. Ответ 18+ 🔞
А, слушай, смотри, вот эта вся хуйня с расширениями в Swift — она, конечно, мощная, но с одним огромным «но», блядь. Нельзя просто так взять и добавить stored property. Вообще нихуя. Это как прийти в гости и начать стену ломать, чтобы шкаф поставить — хозяева охуеют.
А почему, спрашивается, такая жесть?
- Стабильность, ёпта: Представь, что у тебя структура
Pointсxиy. Всё летает. А потом какое-то ебучче расширение из другой либы добавляет тудаz. И всё, пиздец, все экземпляры, созданные до этого, теперь битые — у них в памяти места подzнет! Компилятор такого не позволяет, и правильно делает, сука. - Скорость: Value-типы (структуры, перечисления) копируются молниеносно, потому что размер известен на этапе компиляции. Добавь stored property — и пошла пляска с бубном, размер плавает. Нахуй надо?
Но если очень хочется, а нельзя, что делать?
-
Вычисляемые свойства — наш бро: Они не хранят нихуя, а просто делают вид. Идеально для обёрток над уже существующим дерьмом.
extension UIView { var cornerRadius: CGFloat { get { layer.cornerRadius } set { layer.cornerRadius = newValue } } }Вот видишь? Никакого нового поля, просто удобный доступ к старому. Красота, блядь.
-
Ассоциированные объекты — чёрная магия для Objective-C наследников: Это как привязать к объекту записку на ниточке. Работает только для классов, которые от
NSObjectпроизошли. Runtime, ёбана!import ObjectiveC
extension UIView { private enum AssociatedKeys { static var customTag = "customTag" }
var customTag: String? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.customTag) as? String
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.customTag, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
Выглядит страшновато, но работает. Главное — не увлекаться, а то превратишь код в помойку.
3. **Протоколы с дефолтной реализацией — для умных:** Если нужно добавить поведение, а не состояние. Типа, «все, кто подписан на этот протокол, могут вот эту хуйню делать». Чисто, элегантно, без костылей.
Короче, Swift — не Python, тут просто так в runtime структуру не расширишь. И слава богу, а то был бы пиздец, а не язык.