Mastering macOS Programming
上QQ阅读APP看书,第一时间看更新

Grouping together different data types

Imagine a situation in which we need a function that will handle one of a limited number of types, though we don't know in advance which of those data types will be passed. Let's say we receive a response to an HTTP request, but we may get either a String or an Array of strings. To write a method that will take either of these types could mean that we have to use the Any type as an argument to that method. Yet we know that an attempt to pass, say, an Int is a mistake, and should not compile. Our method that takes an Any argument won't catch that.

We could override the method, providing a version for each data type, but we don't know at compile time which method will be called. So the conditional code starts to spread its ugly traces across our program.

However, there is a better way; we can define an enum that has two cases, each of which is a different type:

enum Response 
{
case string(String)
case array([String])
}

When we create an instance of either case of this enum, we are required by the compiler to provide a value, which is type-checked against the case's type:

let response = Response.string("hi there") 
let response = Response.array(["fox", "socks", "box"])

The method that we write simply has to test the case for its type:

func handleResponse(response: Response) 
{
switch response
{
case .string(let s):
// do one thing
print(s)
case .array(let a):
// do something else
print(a)
}
}

Nothing outside the method needs to start throwing if clauses around and covering the different scenarios. The handleResponse method knows what to do in each case, and accepts complete responsibility for dealing with the different types that may be passed.