Протокол Swift со значениями параметров по умолчанию

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

class Baz {
    func foo(bar: BarType, camp: CampType = CampType()) -> String {
        return "World"
    } 
}

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

protocol BazProtocol {
    func foo(bar: BarType, camp: CampType) -> String
}

И макет:

struct BazMock: BazProtocol {
    func foo(bar: BarType, camp: CampType) -> String {
        return ""
    }
}

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

protocol BazProtocol {
    func foo(bar: BarType, camp: CampType = "Hello") -> String
}

Но вы получите следующую ошибку:

default argument not permitted in a protocol method

Есть способ обойти это ограничение.

На помощь приходят расширения!

Мы не будем определять параметры по умолчанию ни в Baz, ни в BazMock, но мы будем использовать расширение протокола, которое будет единственным местом, где будут определены значения по умолчанию. Таким образом, обе реализации одного и того же протокола имеют одинаковые значения по умолчанию.

extension BazProtocol {
    func foo(
        bar: BarType,
        camp: CampType = CampType()) -> String {
        return foo(bar: bar, camp: camp)
    }
}

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

* Важное примечание * Поскольку протокол BazProtocol уже имеет реализацию по умолчанию из расширения, если вы используете его в объекте и забыли реализовать функцию foo, компилятор не будет жаловаться, но функция расширения foo вызовет сам рекурсивно, пока ваш код не выйдет из строя с BAD_ACCESS.

Все очень просто: у нас есть определения методов протокола со значениями по умолчанию.

Благодарим Костаса Кремизаса и Павлоса-Петроса Турнариса за их отзывы.