Предположим, мой (чрезвычайно упрощенный) код приложения выглядит следующим образом:
// Foo.swift
protocol FooDelegate: class {
func didBar(on foo: Foo)
}
class Foo {
weak var delegate: FooDelegate?
}
private extension Foo {
func _bar() {
self.delegate?.didBar(on: self)
}
}
// Baz.swift
class Baz: FooDelegate {
init() {
let foo: Foo = Foo()
foo.delegate = self
self._foo = foo
}
private var _foo: Foo
func didBar(on foo: Foo) {
print("Bazinga!")
}
}
Поскольку ничего за пределами Foo.swift никогда не читает .delegate
любого экземпляра Foo, я мог бы изменить Foo следующим образом:
// Foo.swift
protocol FooDelegate: class {
func didBar(on foo: Foo)
}
extension Foo {
func setDelegate(_ delegate: FooDelegate?) {
self._delegate = delegate
}
}
class Foo {
private weak var _delegate: FooDelegate?
}
private extension Foo {
func _bar() {
self._delegate?.didBar(on: self)
}
}
Я могу подумать о следующих проблемах:
- это немного больше кода для записи (на самом деле, это немного меньше по сравнению с тем, как я обычно писал бы его, см. Ниже)
- если бы я должен был создать подкласс типа и захотел бы использовать делегат внутри реализации подкласса, мне пришлось бы либо реализовать части подкласса, которые должны использовать делегат внутри Foo.swift, либо сделать переменную делегата внутренне доступной снова
Есть ли другие возможные недостатки?
Если бы код находился в фреймворке, а не в приложении, я бы определенно выставил переменную, чтобы можно было использовать ее в подклассе типа.
В моем коде приложения я хотел бы сделать его доступным для чтения только в том случае, если это действительно необходимо, чего никогда не было в приложении 20000 loc, над которым я работаю.
Как я обычно это пишу:
// Foo.swift
protocol FooDelegate: class {
func didBar(on foo: Foo)
}
extension Foo {
var delegate: FooDelegate? {
get { return self._delegate }
set { self._delegate = newValue }
}
}
class Foo {
private weak var _delegate: FooDelegate?
}
private extension Foo {
func _bar() {
self.delegate?.didBar(on: self)
}
}
Я делаю это потому, что imho облегчает сбор краткого обзора внутреннего / открытого интерфейса типа по сравнению с наличием закрытых и внутренних переменных в объявлении класса. В этом случае это только одна переменная, но представьте, что у вас есть тип, который имеет 10 внутренне доступных переменных, еще 5 переменных, которые доступны только в частном порядке, некоторые из этих переменных слабые, некоторые ленивые, возможно, есть также несколько статических переменных, несколько переопределений (которые также должны быть объявлены в объявлении класса) и некоторые инициализаторы.