Абстракция
Суть
Абстракция — выделение существенного и сокрытие деталей реализации за понятным контрактом. Мы говорим «загрузчик картинок», а не «URLSession + кэш на диске + декодирование». Каждый уровень абстракции позволяет думать о задаче, не держа в голове нижние уровни. Это главный инструмент борьбы со сложностью.
В Swift абстракция — это протокол
В Swift нет абстрактных классов, поэтому контракт описывают протоколом, а реализации — любыми типами (чаще struct).
import Foundation
protocol ImageLoader {
func load(_ url: URL) async throws -> Data
}
struct NetworkImageLoader: ImageLoader {
func load(_ url: URL) async throws -> Data {
try await URLSession.shared.data(from: url).0
}
}
struct CachedImageLoader: ImageLoader {
let base: any ImageLoader
func load(_ url: URL) async throws -> Data {
// check cache, otherwise delegate to `base`
try await base.load(url)
}
}
// Client code knows only the abstraction:
func makeLoader() -> some ImageLoader {
CachedImageLoader(base: NetworkImageLoader())
}
Клиент работает с ImageLoader и не знает, что за ним сеть и кэш. Реализацию можно заменить на стаб в тестах, а some ImageLoader скрывает конкретный тип даже в сигнатуре.
Абстракция vs инкапсуляция
- Абстракция отвечает на вопрос «что умеет объект» (контракт).
- Инкапсуляция — «как он это делает и кто имеет доступ» (защита состояния).
- Они работают вместе: протокол задаёт абстракцию, уровни доступа — инкапсуляцию.
На что смотрит интервьюер
- Умение назвать неудачную абстракцию: «протечка» деталей (метод
loadFromDiskв общемImageLoader), слишком широкие интерфейсы (нарушение ISP), абстракция ради абстракции (протокол с единственной реализацией и без тестов). - Понимание, что
URLSession,FileManager,UIView— тоже абстракции над сокетами, файловой системой и Core Animation.