Комментарии 16
члены класса
Как-то режет глаз. Хоть я давно и не читал русскоязычной литературы на данную тему, но предпочел бы "свойства" (от property) или "поля".
Для абстрактных (базовых) классов в Swift есть один хак:
protocol _MyAbstractProtocol {
func foo()
}
class _MyAbstractClass {
func bar() {
if let base = self as? _MyAbstractProtocol {
base.foo()
}
}
}
typealias MyAbstractClass = MyAbstractClass & _MyAbstractProtocol
class MyConcreteClass: MyAbstractClass {
func foo() {
print("foo")
}
}
Данный способ позволяет уйти от fatalError
для базовых методов обязательных к реализации в наследнике, с их контролем на этапе компиляции в виде бонуса.
Класс-значение
Вы упустили, что данный вид классов в Swift на 99% заменяется структурами.
Я это не упустил, а опустил, так как тема о классах. Под капотом базовые структуры данных работают как ссылочный тип, это необходимо для оптимизации по ряду причин. Моя цель осветить на что обращать внимание при проектировании именно класс-значения. А в большинстве остальных кейсов выбор структуры будет проще и профитнее.
В статье много общих определений из ООП без единого примера на Swift. Из нее сложно почерпнуть что-либо полезное. Новичку она будет совсем непонятна, а для опытного ООП-шника в ней нет ничего нового.
Класс-свойство
Тут вообще непонятно, что вы пытались сказать (как этот термин на английском пишется?), и как его реализовать на Swift.
Это Utility-классы или их еще любят называть Helper-классы. Такие классы очень удобны и их можно встретить в любом проекте. В качестве примера DateUtility.
final class DateUtility {
static func currentDate() -> String {
...
}
static func numberOfDaysInMonth() -> Int {
...
}
static func firstDayOfWeek() -> Int {
...
}
static func dateFor(_ type: DateForType) -> Date {
...
}
}
Основная проблема таких классов в том, что они не обладают состояниями, это просто пространство имен, где сгруппированы методы, которые принимают на вход какие-то параметры что-то с ними делают и возвращают данные.
Еще часто замечаю, что утилитные методы любят прятать в extensions к какому либо типу.
Для этих целей в Swift принято использовать enum'ы без case'ов, так как они не имеют инициализатора по-умолчанию и не позволяют наследование.
Еще часто замечаю, что утилитные методы любят прятать в extensions к какому либо типу.
В Swift есть пространства имен на основе типов, их можно вкладывать один в другой, за исключением протоколов. Чтобы не засорять глобальное пространство имен, все типы-сателиты лучше определять вложенными в основной тип.
Насколько я помню, протоколы в Swift работают аналогично классам в Haskell или трейтам в Rust. Может не стоит натягивать сову на глобус, изображая базовые классы, а начать пользоваться протоколами ?
Верно, для 90% задач протоколов с дефолтной имплементацией должно быть достаточно.
Иногда нужно создать базовый класс на основе библиотечного (например UIViewController
) и тут мой пример с typealias
может пригодиться.
Похоже автор не разобрался до конца в Swift и пытается применить паттерны из C++, при том, что последний с трудом можно назвать ООП-языком.
Проектирование классов на Swift