Распространенный протокол Swift для расширений - PullRequest
0 голосов
/ 15 мая 2018

Широко распространенный протокол для расширений

Swift 4.1, Xcode 9.3

Мне было интересно, каковы некоторые из наиболее всеобъемлющих протоколов в Swift.Я хочу сделать расширение, которое применяется к значениям, которые могут быть установлены.Цель этого состояла в том, чтобы облегчить написание более однострочного кода.


Мое расширение:

Примечание: на данный момент, " всеобъемлющий"протокол, который я расширяю, является Equatable.

extension Equatable {
    @discardableResult public func set(to variable: inout Self) -> Self {
        variable = self
        return self
    }
}

Предостережение: Я хотел бы использовать .set(to: ) длязначения, которые также не соответствуют Equatable.


Использование:

let ten = 10
var twenty = 0

(ten + 10).set(to: &twenty)

print(twenty)
// Prints "20"

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

return value.set(to: &variable)

Последний вопрос

Как мне сделать .set(to: ) более дальновидным, без необходимости использовать его несколько раз?

  • Например, если бы я написал одно и то же расширение для Equatable, CustomStringConvertible, CVarArg, было бы несколько предложений об одинаковых расширениях для многих значений, которые соответствуют всем 3 из них.протоколы.
  • Если это невозможно, то какой лучший всеобъемлющий протокол я могу использовать?

БонусВопрос: есть ли в расширении способ сделать что-то не похожее на extension Equatable where !(Element: CustomStringConvertible) или extension Equatable where !(Element == Int) (используйте предикат where для целей исключения) ?


1 Ответ

0 голосов
/ 15 мая 2018

В большинстве случаев я категорически против такого рода кода.«Однострочный» код, как правило, не является целью Swift.Четкая и краткая цель - это четкая победа в конфликте.Расширение Any таким образом (даже если это было законно), как правило, является очень плохой идеей, поскольку set(to:) может легко столкнуться.

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

infix operator -->
private func --> <T>(lhs: T, rhs: inout T) -> T {
    rhs = lhs
    return lhs
}

let ten = 10
var twenty = 0

(ten + 10) --> twenty

print(twenty)
// Prints "20"

Более естественный способ сделать то, что вы описываете, - это протоколы, которые вы явно согласуете.Например:

protocol Settable {}

extension Settable {
    @discardableResult public func set(to variable: inout Self) -> Self {
        variable = self
        return self
    }
}

extension Int: Settable {}
extension String: Settable {}
extension Array: Settable {}
extension Optional: Settable {}

Вы можете присоединить Settable к любым типам, которые полезны для этой цели, и эти расширения могут быть предоставлены в любом месте проекта (даже в других модулях).В Swift нет способа прикрепить метод к каждому возможному типу.

...