Textual Representation for Classes in Swift

This post is dated. See post for latest

To get println() or similar methods to emit a textual representation (like Java’s toString()) of a class, Swift recommends adopting one of these protocols, and in this order:

    • Streamable
/// Models an object that can be written to an `OutputStream` in a single,
/// immediately obvious, way.
///
/// For example: `String`, `Character`, `UnicodeScalar`.
protocol Streamable {
    func writeTo<Target : OutputStream>(inout target: Target)
}
    • Printable
/// This protocol should be adopted by types that wish to customize their
/// textual representation.  This textual representation is used when objects
/// are written to an `OutputStream`.
protocol Printable {
    var description: String { get }
}
    • DebugPrintable
/// This protocol should be adopted by types that wish to customize their
/// textual representation used for debugging purposes.  This textual
/// representation is used when objects are written to an `OutputStream`.
protocol DebugPrintable {
    var debugDescription: String { get }
}

And just for completeness, printf is defined as:

/// The textual representation is obtained from the `object` using its protocol
/// conformances, in the following order of preference: `Streamable`,
/// `Printable`, `DebugPrintable`.
///
/// Do not overload this function for your type.  Instead, adopt one of the
/// protocols mentioned above.
func println<T>(object: T)

Well, it doesn’t work. When we print this class with println():

class X : Printable  {
  var description: String{
    return "This is class X"
  }
}

println(X())

The output isn’t from the description variable, rather we see the system default:

C11lldb_expr_01X (has 0 children)

Replacing var description with a func doesn’t help either.

The only way we’be been able to get println() and for that matter with NSLog is to inherit from NSObject and use func description() (like in Objective C). Apparently, as the introduction documentation points out, Swift objects don’t inherit from a root like Object in Java.

class ABC : NSObject  {
   func description() -> String {
    return "This is class ABC"
  }
}

NSLog("%@", [ABC()])
println(ABC())

Gives us:

2014-06-04 15:51:17.142 PlaygroundStub_OSX[25721:303] (
    "This is class ABC"
)
This is class ABC

Much better. (Note that the second parameter to NSLog is an explicit array).

Instead of func description, a var can also be used, but it must be overridden:

  override  var description: String {
    return "Some description"
  }

As an aside, don’t even attempt to log with NSLog unless your object inherits from NSObject. See this.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s