Menu
Coddy logo textTech

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:) によって使用されるため、1つのプロパティですべての値の表示箇所を制御できます。

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(_:_:) を作成してください。

提供されたコードは、1 行につき 1 つの分数 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プレイグラウンド