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

Adding operator implementations to types

This sounds so complicated, but it is, in fact, really easy. All we need to do is define an implementation of any given operator for any given type.

For the time being, we'll use a custom type, although what we are doing can be used equally effectively for Swift and Cocoa types.

We'll start by defining a custom type:

struct GridMovement 
{
let rows: Int
let cols: Int
}

Now that we have it, we notice that it would make perfect sense to be able to apply some basic arithmetical operators to our type. We could add these to the main type declaration, but convention (young though it is) suggests we put it in an extension:

extension GridMovement 
{
static func + (lhs: GridMovement,
rhs: GridMovement) -> GridMovement
{
let rows = lhs.rows + rhs.rows
let cols = lhs.cols + rhs.cols
return GridMovement (rows: rows, cols: cols)
}
}

As you can see, we're treating the + operator as we would any method name, though we do need to declare it to be static, making it a type method rather than an instance method.

So, we can now add two GridMovement together. How about multiplying a GridMovement by an Int?

  static func * (multiplier: Int, 
movement: GridMovement) -> GridMovement
{
let rows = multiplier * movement.rows
let cols = multiplier * movement.cols
return GridMovement (rows: rows, cols: cols)
}

static func * (movement: GridMovement,
multiplier: Int) -> GridMovement
{
let rows = movement.rows * multiplier
let cols = movement.cols * multiplier
return GridMovement (rows: rows, cols: cols)
}

Note that we have to provide (Int, GridMovement) and (GridMovement, Int) signatures, because we don't know in which order they will be called.

Now let's round it off with the += operator:

  static func += (lhs: inout GridMovement, 
rhs: GridMovement)
{
lhs = lhs + rhs
}

Pretty simple, having already implemented the + operator.

Run the following code to check it all worked out:

var movementA = GridMovement (rows: 3, cols: 5) 
movementA = movementA * 2
print(movementA)
var movementB = GridMovement (rows: 11, cols: 13)
let movementC = movementA + movementB
print(movementC)