Приведи пример использования протокола в Swift.

Ответ

Протокол определяет интерфейс (требуемые свойства и методы), который должны реализовать соответствующие ему типы (классы, структуры, перечисления).

Пример:

// 1. Объявление протокола
protocol Vehicle {
    var numberOfWheels: Int { get }
    func startEngine()
}

// 2. Реализация протокола классом
class Car: Vehicle {
    let numberOfWheels = 4

    func startEngine() {
        print("Car engine started")
    }
}

// 3. Реализация протокола структурой
struct Bike: Vehicle {
    let numberOfWheels = 2

    func startEngine() {
        print("Bike pedaling started")
    }
}

// 4. Использование полиморфизма
let vehicles: [Vehicle] = [Car(), Bike()]
for vehicle in vehicles {
    print("Wheels: (vehicle.numberOfWheels)")
    vehicle.startEngine()
}

Почему это полезно:

  • Полиморфизм: Массив [Vehicle] может хранить объекты разных типов, но с общим интерфейсом.
  • Проектирование: Протоколы позволяют определять контракты и абстрагироваться от конкретной реализации.
  • Тестирование: Облегчают создание мок-объектов для модульного тестирования.

Ответ 18+ 🔞

Да ты посмотри, какая хуйня интересная! Ну, в смысле, протоколы в свифте. Представь себе, что протокол — это как бумажка от жены с требованиями на день. Там написано: «Должен иметь свойство numberOfWheels (количество колёс) и уметь выполнять метод startEngine() (заводить движок)». И неважно, кто ты — мужик на тачке или хипстер на велике. Если к тебе пришла эта бумажка, ты, блядь, обязан эти пункты выполнить, иначе пиздец.

Вот смотри, как это выглядит в коде, тут всё чётко:

// 1. Вот та самая бумажка-приказ, протокол
protocol Vehicle {
    var numberOfWheels: Int { get }
    func startEngine()
}

// 2. Класс "Тачка" получает бумажку и чешет затылок: "Ну ладно..."
class Car: Vehicle {
    let numberOfWheels = 4 // «Имею четыре колеса, мать их, вот они!»

    func startEngine() {
        print("Car engine started") // «Движок завёлся, врум-врум!»
    }
}

// 3. Структура "Велик" тоже не лыком шита, принимает вызов
struct Bike: Vehicle {
    let numberOfWheels = 2 // «Два колеса, ёпта, и гордиться нечем»

    func startEngine() {
        print("Bike pedaling started") // «Движок — это мои ноги, поехали!»
    }
}

А теперь самое охуенное! Берём их всех — и тачку, и велик — и суём в один массив [Vehicle]. И похуй, что они разные! Главное — у каждого есть numberOfWheels и метод startEngine(). И мы можем пройтись по массиву и каждого заставить эти штуки показать.

// 4. Собираем зоопарк транспорта в одну кучу
let vehicles: [Vehicle] = [Car(), Bike()]
for vehicle in vehicles {
    print("Wheels: (vehicle.numberWheels)") // Спрашиваем колёса
    vehicle.startEngine() // Приказываем завестись
}

И нахуя это всё, спросишь? А вот нахуя:

  • Полиморфизм, ёпта! Это когда ты можешь в одну переменную или массив запихнуть что угодно — Car, Bike, Tank — лишь бы они подписались под один протокол. И потом со спокойной жопой вызывать у всех общие методы. Удобно, блядь, как!
  • Проектирование от хуя к пальцу. Сначала думаешь, что должен уметь объект (пишешь протокол), а потом уже лепишь под него реализацию. Не наоборот, чтобы не получилась каша из говна и палок.
  • Тестирование без боли. Хочешь протестировать какой-нибудь модуль, который ждёт объект Vehicle? Да похуй! Сделай на коленке «пустышку» — MockVehicle, которая реализует протокол, но внутри просто пишет в лог. И тестируй на здоровье, не разоряя гараж.

Короче, протоколы — это сила. Они заставляют код держать лицо и не выёбываться.