Menu
CoddyTech

CustomStringConvertible

本课属于 Coddy Swift 学习旅程的“面向对象编程”单元。第 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 在线编辑器