Ответ
В Swift существует три основных типа методов, отличающихся областью видимости и возможностью полиморфизма.
1. Метод экземпляра (Instance Method)
Работает с конкретным экземпляром класса/структуры. Имеет доступ к свойствам экземпляра через self.
class Counter {
var count = 0
// Метод экземпляра
func increment() {
count += 1 // Доступ к свойству экземпляра
print(count)
}
}
let myCounter = Counter()
myCounter.increment() // Вызов требует экземпляр
2. Метод класса (Class Method)
Объявляется с ключевым словом class func. Вызывается на самом типе, а не на экземпляре. Поддерживает переопределение в подклассах.
class Vehicle {
class func description() -> String {
return "A general vehicle"
}
}
class Car: Vehicle {
// Может быть переопределен
override class func description() -> String {
return "A car with wheels"
}
}
print(Vehicle.description()) // "A general vehicle"
print(Car.description()) // "A car with wheels" (полиморфизм)
3. Статический метод (Static Method)
Объявляется с static func. Аналогичен методу класса, но не может быть переопределен в подклассах. Используется для утилитарных функций.
class MathUtils {
static func square(_ x: Int) -> Int {
return x * x
}
}
class AdvancedMath: MathUtils {
// Ошибка компиляции: нельзя переопределить static метод
// override static func square(...) {}
}
print(MathUtils.square(5)) // 25
Сводка различий
| Характеристика | Метод экземпляра | Метод класса (class) |
Статический метод (static) |
|---|---|---|---|
| Вызов | На экземпляре: obj.method() |
На типе: Type.method() |
На типе: Type.method() |
Доступ к self |
Экземпляр (self.property) |
Тип (Self.self) |
Тип (Self.self) |
| Переопределение | Да (если не final) |
Да | Нет |
| Использование | Работа с состоянием объекта | Фабричные методы, полиморфные утилиты | Чисто утилитарные функции |
Практический совет: используйте static по умолчанию для методов, не требующих полиморфизма. Переходите на class только если планируете переопределение в подклассах.
Ответ 18+ 🔞
А, ну это же про методы в Swift! Слушай, тут, блядь, целых три вида, и каждый со своим характером, как люди в очереди за колбасой. Один — конкретный работяга, второй — начальник отделения, а третий — вообще, типа, указ сверху, который не оспаривается. Ёпта, сейчас разжуем.
Первый тип — метод экземпляра. Это самый простой пацан. Он привязан к конкретной сущности, к этому вот объекту. Без экземпляра — он никто и звать его никак. Как будто ты кричишь «Вася!», а в комнате никого нет. Вот и он так же.
class Counter {
var count = 0
// Метод экземпляра
func increment() {
count += 1 // Доступ к свойству экземпляра
print(count)
}
}
let myCounter = Counter()
myCounter.increment() // Вызов требует экземпляр
Видишь? myCounter.increment(). Без myCounter этот increment — просто набор букв в памяти, грустный и никому не нужный. У него есть доступ к self, то есть к внутренностям этого самого счетчика. Работяга, одним словом.
Второй — метод класса (class func). Вот это уже поинтереснее. Это как начальник цеха, который может давать указания от имени всего завода. Вызываешь ты его не на объекте, а на самом типе. И главная его фишка — полиморфизм, ёбта! Его можно переопределить в наследниках. То есть, если папаша сказал одно, то сынок может сказать другое, и все будут слушать сынка, когда обращаются к нему.
class Vehicle {
class func description() -> String {
return "A general vehicle"
}
}
class Car: Vehicle {
// Может быть переопределен
override class func description() -> String {
return "A car with wheels"
}
}
print(Vehicle.description()) // "A general vehicle"
print(Car.description()) // "A car with wheels" (полиморфизм)
Вот смотри: спрашиваем у Vehicle — он мямлит что-то общее. Спрашиваем у Car — а он уже конкретику выдает. Это и есть магия переопределения. class — это как разрешение на семейные разборки.
Третий — статический метод (static func). А это, сука, уже не метод, а приказ из министерства. Закон. Истина в последней инстанции. Вызывается тоже на типе, но переопределить его — ни хуя! Компилятор тебе такую ошибку выдаст, что мало не покажется. Он для утилиток, которые должны работать одинаково всегда и везде, и нечего тут умничать.
class MathUtils {
static func square(_ x: Int) -> Int {
return x * x
}
}
class AdvancedMath: MathUtils {
// Ошибка компиляции: нельзя переопределить static метод
// override static func square(...) {} // Пиздец тебе, а не переопределение!
}
print(MathUtils.square(5)) // 25
Попробуй в наследнике переписать — получишь по ебалу от компилятора. «Не-не-не, дружок, тут власть моя».
А теперь, блядь, сводка для тех, кто в танке или просто забыл:
| Признак | Метод экземпляра | Метод класса (class) |
Статик (static) |
|---|---|---|---|
| Кого звать? | Объект: obj.method() |
Тип: Type.method() |
Тип: Type.method() |
Кто его self? |
Сам экземпляр | Сам тип (класс) | Сам тип (класс) |
| Можно переписать? | Да (если не final) |
Ага, можно! | Ни хуя! |
| Зачем нужен? | Ковыряться в данных объекта | Фабрики, общие штуки с полиморфизмом | Утилиты, законы, константы |
И мой тебе совет, на правах старого ворчуна: начинай всегда со static. Это как поставить замок. Если потом окажется, что метод должен быть полиморфным и его надо переопределять — вот тогда уже меняй на class. А так — static и не парись. Проще жить будет, волнение ебать.