Swift: AnyObject is not your only option for mixing things up ('Collections of Protocol Types')


There is a choice when creating arrays. We are encouraged to strongly type them (i.e. use a single type) but when needed use the AnyObject protocol (and also Any) to mix types.
[Equatable]() // error
[SequenceType]()  // error
[SignedIntegerType]()  // error
Outside of generic functions, Swift's own protocols are not typically used in place of types. Although there are exceptions. For example BooleanType, Printable (and of course AnyObject itself):
var bol = [BooleanType]() // OK
bol.append(true) // OK
The rule appears to be that protocols which require a reference to self in their methods (or in the methods of protocols they adopt) are not able to be used as the basis for restriction of types in arrays.

Note: NSArray and NSMutableArray are at our disposal as well, but I'm focusing on Swift types here rather than Cocoa classes.

Roll your own protocol

There is a way around this all or nothing approach, however, by making your own protocol and having certain types adopt it.
protocol Mixed {
}

extension String:Mixed {
}

extension Array:Mixed {
}

extension Dictionary:Mixed {
}
This allows you to then create a mixed array that only allows those types adopting the protocol to be appended:
var a:[Mixed] = ["String",[1,2,3],["one":1,"two":2]]
a.append(1) // error
To read a little bit more about this, see the Apple docs (under the heading of 'Collections of Protocol Types').

Pushing the limits

One other thing: while the array restricts the types to those adopting the (Mixed) protocol, nested arrays can take AnyObject.
var a:[Mixed] = ["String",[1,2,[1,2,3,"string"]],["one":1,"two":2]]
Strong typing it would seem goes out of the window. Use wisely.

Endorse on Coderwall

Comments

  1. That seems like cheating. But could be useful.

    ReplyDelete
    Replies
    1. I agree. This is more an example of what can be done than what should be done.

      Delete
    2. An arguably safer approach for when a mixed set of types is need is to define an enum where each case wraps one of the desired types.

      Delete
    3. An example of this would be great if you have one to share.

      Delete

Post a Comment