Menu
Coddy logo textTech

CustomStringConvertible

Часть раздела Объектно-ориентированное программирование путешествия по Swift на Coddy. Урок 37 из 57.

При выводе значения Swift по умолчанию показывает его тип и свойства, а для класса — только имя типа. Соответствие CustomStringConvertible и предоставление description позволяет управлять текстом:

struct Money {
    let cents: Int
}
struct Price: CustomStringConvertible {
    let cents: Int
    var description: String { "$\(cents / 100).\(cents % 100)" }
}

print(Money(cents: 1250))
print(Price(cents: 1250))

Результат:

Money(cents: 1250)
$12.50

description используется print, интерполяцией строк и String(describing:), поэтому одно свойство управляет каждым местом, где отображается значение:

struct Point: CustomStringConvertible {
    let x: Int, y: Int
    var description: String { "(\(x), \(y))" }
}

let p = Point(x: 2, y: 5)
print("start at \(p)")
print([p, Point(x: 0, y: 0)])
print(String(describing: p).count)

Результат:

start at (2, 5)
[(2, 5), (0, 0)]
6

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

class Account {
    let owner: String
    var balance: Int
    init(owner: String, balance: Int) { self.owner = owner; self.balance = balance }
}

class NamedAccount: CustomStringConvertible {
    let owner: String
    var balance: Int
    init(owner: String, balance: Int) { self.owner = owner; self.balance = balance }
    var description: String { "\(owner): \(balance)" }
}

print(Account(owner: "Ada", balance: 5))
print(NamedAccount(owner: "Ada", balance: 5))

Вывод:

main.Account
Ada: 5

Делайте description коротким и понятным для людей. Он не предназначен для разбора и не должен изменять значение:

enum Status: CustomStringConvertible {
    case active, suspended
    var description: String {
        switch self {
        case .active: return "active"
        case .suspended: return "suspended"
        }
    }
}
challenge icon

Задание

Легко

Сделайте структуру Fraction (числитель, знаменатель) соответствующей протоколу CustomStringConvertible. Её description отображает дробь в несократимом виде: 6/8 выводится как 3/4, 4/2 — как 2, 0/5 — как 0, а отрицательная дробь сохраняет знак перед числом (-1/2). Напишите вспомогательную функцию gcd(_:_:) для сокращения дроби.

Предоставленный код считывает дроби a/b, по одной в каждой строке, и выводит каждую из них с помощью print.

Ваш код должен находиться в файлах Fraction.swift и Functions.swift. В файле main.swift находится предоставленный код ввода/вывода, и его нельзя редактировать.

Попробуйте сами

// Предоставленный код ввода/вывода: оставьте его как есть
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
    let p = line.split(separator: "/").map { Int($0)! }
    print(Fraction(numerator: p[0], denominator: p[1]))
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Песочница Swift