Swift
November 13

Как добавить хранимое свойство в extension для структур или классов?

Недавно я подробно разобрал один из самых популярных вопросов на собеседованиях: можно ли добавлять хранимые свойства в расширения классов или структур? Представим ситуацию: нам действительно нужно добавить такое свойство, но мы хотим сделать это не напрямую.

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

Тем не менее, в этой статье я предлагаю рассмотреть несколько альтернативных подходов, которые помогут обойти данное ограничение.

1. Использование протоколов

Одним из решений может стать использование протоколов. Вы можете определить протокол с необходимыми свойствами, а затем реализовать его в вашем основном классе или структуре. Например:

protocol PersonProtocol {
    var age: Int { get set }
}

struct Person: PersonProtocol {
    var name: String
    var age: Int
}

extension Person {
    mutating func celebrateBirthday() {
        age += 1
        print("Happy birthday, \(name)! Now you are \(age) y.o.")
    }
}

Такой подход не только позволяет соблюдать принципы SOLID, но и делает код более ясным и гибким.

2. Использование вычисляемых свойств

Хотя вы не можете добавить хранимое свойство через расширение, вы можете использовать вычисляемые свойства, чтобы эмулировать его поведение. Например:

struct Person {
    var name: String
}

extension Person {
    var isAdult: Bool {
        return age >= 18
    }
}

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

3. Создание обертки

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

struct PersonWrapper {
    var person: Person
    var additionalInfo: String?
    
    func displayInfo() {
        print("Name: \(person.name), Additional Info: \(additionalInfo ?? "No info")")
    }
}

Такое решение создаст дополнительный уровень абстракции, упростив управление данными и сохранив при этом читаемость и чистоту кода.

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

👍 Если вам понравилась статья, не забудьте поставить лайк и подписаться на обновления, чтобы не пропустить новые материалы!