В чем разница между ключевыми словами some и any для протоколов в Swift?

Ответ

some (непрозрачный тип) и any (экзистенциальный тип) — это два способа абстрагирования типов через протоколы, но с фундаментальными различиями в производительности и семантике.

some (Opaque Type)

  • Указывает, что возвращается конкретный, фиксированный тип, реализующий протокол. Конкретный тип известен компилятору, но скрыт от вызывающей стороны.
  • Статическая диспетчеризация: вызовы методов разрешаются на этапе компиляции, что дает максимальную производительность.
  • Требует, чтобы из одной точки возврата всегда возвращался один и тот же конкретный тип.
func makeVehicle() -> some Vehicle {
    return Car() // Компилятор знает, что это Car, но для внешнего кода это "some Vehicle"
}
// let v = makeVehicle() // Тип v — some Vehicle (фактически Car)

any (Existential Type)

  • Указывает на любой тип, реализующий протокол. Конкретный тип может меняться и определяется в runtime.
  • Динамическая диспетчеризация: вызовы методов проходят через таблицу виртуальных функций (witness table), что добавляет небольшие накладные расходы.
  • Позволяет хранить в одной коллекции объекты разных типов, реализующих один протокол.
func wash(_ vehicle: any Vehicle) {
    // Принимает любой тип, реализующий Vehicle
    vehicle.clean()
}

var garage: [any Vehicle] = [Car(), Bicycle()] // Массив разных типов
Ключевые отличия: Аспект some any
Производительность Выше (статическая диспетчеризация) Ниже (динамическая диспетчеризация, boxинг)
Гибкость Один конкретный тип Любой совместимый тип
Использование Возвращаемые типы, свойства Параметры, коллекции гетерогенных типов

Совет: По умолчанию предпочитайте some для возвращаемых типов из-за производительности. Используйте any, когда нужна runtime-гибкость.

Ответ 18+ 🔞

А, ну вот, опять эти ваши some и any! Сидишь, блядь, читаешь, а в глазах рябит. Сейчас я тебе так объясню, что ты, сука, не то что поймёшь — ты прочувствуешь это на своей шкуре, как будто хуем по лбу получил.

Смотри сюда, умник. Есть два пути, блядь. Первый — some. Это как если бы ты заказал в столовой «какое-нибудь первое». Тебе, конечно, принесут что-то конкретное — допустим, борщ, ёпта. Повар-то знает, что это борщ, и он его сварил по своему, блядь, фирменному рецепту. Но для тебя, жопы с глазами, это просто «какое-то первое». Суть в чём? Тип-то внутри конкретный и фиксированный, просто от тебя его скрыли, как грех за пазухой. И когда ты этот борщ жрёшь, всё происходит быстро — ложка в рот, и понеслась. Это статическая диспетчеризация, на максимальной скорости, без лишних телодвижений.

func сделайТачку() -> some Транспорт {
    return Машина() // Для компилятора тут ясно — Машина. Для тебя — просто «какой-то транспорт».
}
// let тачка = сделайТачку() // Тип `тачки` — some Транспорт (а внутри-то, блядь, Машина!)

А теперь второй путь — any. Это уже полный пиздец и свобода, блядь. Это как придти в ту же столовую и сказать: «Дайте мне ЛЮБОЕ первое, какое у вас есть». Тебе могут впарить и борщ, и щи, и даже, прости господи, харчо. Конкретный тип определяется прямо на месте, когда повар суёт половник в котёл. И когда ты это ешь, приходится каждый раз уточнять: «А это что за херня?». Это динамическая диспетчеризация, с лишними проверками, как будто ты на каждом шагу паспорт показываешь. Накладные расходы, блядь, вот они где!

func помой(_ транспорт: any Транспорт) {
    // Принимает ЧТО УГОДНО, что умеет быть транспортом. Велосипед? Пожалуйста. Танк? Иди нахуй, но тоже можно.
    транспорт.помойся()
}

var гараж: [any Транспорт] = [Машина(), Велосипед()] // Вот она, солянка сборная, сука! Разные типы в одной куче.

Так в чём, блядь, соль, спросишь ты? А соль вот в этой таблице, в рот меня чих-пых:

Что сравниваем some (Непрозрачный) any (Экзистенциальный)
Скорость Овердохуища! Всё решается при компиляции. Помедленнее, ибо танцы с бубном в рантайме.
Гибкость Один тип, и хрен с горы. Любой тип, хоть весь зоопарк собирай.
Когда юзать Для возвращаемых значений, чтоб не париться. Когда в параметры или в массив нужно всякой хуйни напихать.

Финал, блядь, мораль: если можешь — всегда жми на some, это как ехать по трассе без пробок. А any — это уже объезд через хуеву деревню, когда другого выхода нет. Понял, да? Иди, делай.