Swift
Java
toString
Swift programming
String representation

Swift equivalent of Java toString

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Swift does not have a method named toString() in the Java sense. The closest equivalent is conforming a type to CustomStringConvertible and implementing the description property.

The Closest Equivalent: CustomStringConvertible

In Java, you override toString() so printing an object gives a useful representation. In Swift, you usually conform to CustomStringConvertible.

swift
1import Foundation
2
3struct User: CustomStringConvertible {
4    let name: String
5    let age: Int
6
7    var description: String {
8        "\(name) (age: \(age))"
9    }
10}
11
12let user = User(name: "Ava", age: 30)
13print(user)
14print(String(describing: user))

Both print(user) and String(describing: user) use the description value.

Why This Is Not Literally toString()

Swift relies more on protocols and generic string conversion than on a universal base-class override point. That means the concept exists, but the mechanism is more protocol-oriented.

A rough comparison is:

  • Java toString() maps to Swift description
  • Java System.out.println(obj) maps to Swift print(obj)
  • Java debug-style object output maps to Swift debugPrint(obj) or String(reflecting: obj)

That is the right mental model when moving between the languages.

Debug Output: CustomDebugStringConvertible

If you want a more detailed representation for debugging, use CustomDebugStringConvertible as well.

swift
1import Foundation
2
3struct Point: CustomStringConvertible, CustomDebugStringConvertible {
4    let x: Double
5    let y: Double
6
7    var description: String {
8        "(\(x), \(y))"
9    }
10
11    var debugDescription: String {
12        "Point(x: \(x), y: \(y))"
13    }
14}
15
16let p = Point(x: 3.0, y: 4.0)
17print(p)
18debugPrint(p)
19print(String(reflecting: p))

Use description for normal output and debugDescription for developer-oriented detail.

Classes, Structs, And Enums

The pattern works across Swift types.

For a class:

swift
1class Vehicle: CustomStringConvertible {
2    let make: String
3    let model: String
4
5    init(make: String, model: String) {
6        self.make = make
7        self.model = model
8    }
9
10    var description: String {
11        "\(make) \(model)"
12    }
13}

For an enum:

swift
1enum Direction: CustomStringConvertible {
2    case north
3    case south
4    case east
5    case west
6
7    var description: String {
8        switch self {
9        case .north: return "North"
10        case .south: return "South"
11        case .east: return "East"
12        case .west: return "West"
13        }
14    }
15}

The key idea is always the same: define the string representation through a protocol conformance.

String Interpolation Uses The Same Idea

Swift string interpolation also uses the object's string representation.

swift
let user = User(name: "Noah", age: 27)
let message = "Current user: \(user)"
print(message)

That is one reason CustomStringConvertible feels like Swift's version of toString(): the representation flows naturally into printing and interpolation.

Default Output Versus Custom Output

Some Swift types already print reasonably well without custom code, especially structs with simple stored properties. But that default output is not a stable contract and may not match what you want users or logs to see.

If the textual form matters, define it explicitly.

That is especially true for:

  • user-facing messages
  • log lines you want to keep readable
  • domain objects where only some fields matter
  • security-sensitive types where you should not print everything

Common Pitfalls

The most common mistake is looking for a toString() override and missing the protocol-based design. In Swift, the right place is description, not a method with the Java name.

Another mistake is using description for expensive work. Printing can happen often, so keep the representation cheap and deterministic.

Developers also confuse normal and debug output. print uses description, while debugPrint and String(reflecting:) prefer the debug form.

Finally, be deliberate about what you expose. A good string representation should help readers, not dump every internal field by default.

Summary

  • Swift's closest equivalent to Java's toString() is CustomStringConvertible with description.
  • 'print(obj) and String(describing: obj) use that representation.'
  • Use CustomDebugStringConvertible for debug-focused output.
  • The pattern works for structs, classes, and enums.
  • Think of Swift string conversion as protocol-based rather than base-class-based.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.