extension
:
class SomeType {}
extension SomeType {
// новая функциональность для типа SomeType будет объявлена здесь
}
Если Вы объявляете расширение для добавления новой функциональности существующему типу, то новая функциональность будет доступна на всех существующих объектах данного типа, даже если они созданы до объявления расширения.
Double
для предоставления базовой поддержки для работы с единицами дистанции:
extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
print("One inch is \(oneInch) meters")
// Выведет "One inch is 0.0254 meters"
let threeFeet = 3.ft
print("Three feet is \(threeFeet) meters")
// Выведет "Three feet is 0.914399970739201 meters"
Эти вычисляемые свойства выражают то, что значение Double
следует рассматриваться в качестве единицы длины. И хотя они реализованы как вычисляемые свойства, имена этих свойств могут быть добавлены к литералу чисел с плавающей точкой через точечный синтаксис, что позволить использовать такие литералы для выполнения преобразования дистанции.
Double
значением 1.0 представляет "один метр". Потому вычисляемое свойство m возвращает self
: выражение 1.m будет вычислено в значение Double
, равно 1.0.
km
умножает значение на 1_000.00 для преобразования в число, выраженное в метрах. Аналогично, в метре содержится 3.28084 футов, так что вычисляемое свойство fr
делит содержащееся значение Double
на 3.28084 для преобразования из футов в метры.
get
для краткости. Их возвращаемой значение имеет тип Double
и может быть использовано в рамках математических вычислений, в которых принимается значение Double
:
let aMarathon = 42.km + 195.m
print("A marathon is \(aMarathon) meters long")
// Выведет "A marathon is 42195.0 meters long"
Расширения могут добавлять новые вычисляемые свойства, но они не могут добавлять новых хранимые свойства или наблюдатели свойств для существующих свойств.
Rect
для представления геометрической фигуры. Пример также определяет две поддерживающих структуры с названием Size
и Point
, каждая из которых предоставляет значение по-умолчанию для всех своих свойств:
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
}
Rect
предоставляет значения по-умолчанию для всех своих свойств, то она получает конструктор по-умолчанию и почленный инициализатор автоматически. Эти инициализаторы могут быть использованы для создания объектов Rect
:
let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0))
Rect
для предоставления дополнительного инициализатора, который принимает конкретную точку центра и размер:
extension Rect {
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
center
и значении value
. Затем инициализатор вызывает автоматический почленный инициализатор init(origin:size:)
, которые сохраняет соответствующие значения начала координат и длины в свойства:
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
size: Size(width: 3.0, height: 3.0))
// начало centerRect теперь равно (2.5, 2.5) и его размеры равны (3.0, 3.0)
Если Вы предоставите новый инициализатор с помощью расширения, то Вы всё ещё будете ответственны за то, чтобы каждый объект был полностью инициализирован по завершению выполнения инициализатора.
repetitions
типу Int
:
extension Int {
func repetitions(task: () -> Void) {
for _ in 0..< self {
task()
}
}
}
Метод repetitions(task:)
принимает единственный аргумент типа () -> Void
, который указывает на то, что функция не имеет параметров и не может возвращать значения.
repetitions(task:)
на любом целом числе для выполнения задачи заданной число раз:
3.repetitions {
print("Hello!")
}
// Hello!
// Hello!
// Hello!
self
или его свойства должны быть помечены как mutating
, как и оригинальные методы мутирующие из основной реализации.
square
типу Int
, который возводит в квадрат оригинальное значение:
extension Int {
mutating func square() {
self = self * self
}
}
var someInt = 3
someInt.square()
// someInt теперь равен 9
Int
. Этот сабскрипт [n] возвращает десятичную цифру на расстоянии n знаков от правой стороны числа:
extension Int {
subscript(digitIndex: Int) -> Int {
var decimalBase = 1
for _ in 0..< digitIndex {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}
746381295[0]
// вернёт 5
746381295[1]
// вернёт 9
746381295[2]
// вернёт 2
746381295[8]
// вернёт 7
Int
не имеет достаточно знаков для запрашиваемого индекса, то реализация сабскрипта вернёт 0, как если бы число было бы дополнено на такое число нулей слева:
746381295[9]
// вернёт 0, как если бы Вы запросили:
0746381295[9]
extension Int {
enum Kind {
case negative, zero, positive
}
var kind: Kind {
switch self {
case 0:
return .zero
case let x where x > 0:
return .positive
default:
return .negative
}
}
}
Это пример добавляет новое вложенное перечисление в Int
. Это перечисление с названием Kind
выражает вид числа, которое представляется отдельным целым числом. Конкретно, он выражает, является ли оно отрицательным, положительным или нулём.
Int
с названием kind
, которое возвращает соответствующий кейс перечисления для этого целого числа.
Int
:
func printIntegerKinds(_ numbers: [Int]) {
for number in numbers {
switch number.kind {
case .negative:
print("- ", terminator: "")
case .zero:
print("0 ", terminator: "")
case .positive:
print("+ ", terminator: "")
}
}
print("")
}
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
// Выведет "+ + - 0 - 0 +"
Эта функция printIntegerKinds(_:)
принимает входной массив значение Int
и итерируется через эти значения по очереди. Для каждого целого в массиве функция определяет значение вычисляемого свойства kind
, а затем выводит соответствующее описание.
number.kind
заранее имеет тип Int.Kind
. Ввиду этого все значения кейсов Int.Kind
могут быть записаны в краткой форме внутри инструкции switch
, например как .negative
вместо Int.Kind.negative
.