Exploring Swift’s Generics: Part Deux

Unlike the Mel Brooks movie, History of the World, Part I, the “Exploring Swift’s Generics: Part 1” post will get its sequel. Since I deferred the discussion of protocols, that will be the subject of Part II.

Here is the code that we’ll reuse from the previous example:

class Magic {
    func cast() -> String {
        return ""
    }
}

class BlackMagic: Magic {
    override func cast() -> String {
        return ""
    }
}

class WhiteMagic: Magic {
    override func cast() -> String {
        return ""
    }
}

class Fire: BlackMagic {
    override func cast() -> String {
        return "Fire!"
    }
}

class Ice: BlackMagic {
    override func cast() -> String {
        return "Ice!"
    }
}

class Cure: WhiteMagic {
    override func cast() -> String {
        return "Cure!"
    }
}

class Antidote: WhiteMagic {
    override func cast() -> String {
        return "Antidote!"
    }
}

 
The thing that I found strangest about trying to implement a generic protocol is that you can’t. Protocols use a different syntax altogether. When working with protocols, we’ll use what are called “associated types” to achieve generic-like functionality via the typealias keyword.

Here is how we define the protocol (“mage protocol” sounds pretty awesome, doesn’t it?):

protocol MageProtocol {
    typealias MagicType: Magic

    func castAll(items: [MagicType])
}

 
Notice that we are able to specify a constraint for our type alias, which will come in handy.

Here is one way we could use our protocol to create a mage that only casts black magic:

class BlackMage: MageProtocol {
    typealias MagicType = BlackMagic
    
    func castAll(items: [BlackMagic]) {
        for item in items {
            println(item.cast())
        }
    }
}

BlackMage().castAll([Fire(), Ice()])

 
One shortcoming, in my opinion, of inheriting from a generic class in Swift is that the subclass has to be generic as well. In the case of the protocol, however, there is no need for a generic.

That is not to say that we cannot take advantage of generics:

class Mage<T: Magic> : MageProtocol {
    typealias MagicType = T
    func castAll(items: [T]) {
        for item in items {
            println(item.cast())
        }
    }
}

Mage<WhiteMagic>().castAll([Cure()])

 
Pay attention to the fact that I had to specify a constraint for the generic type that was compatible with the protocol’s type alias.

It seems to me that implementing a protocol with associated types, rather than inheriting from a generic base class, is the cleaner solution (review “Exploring Swift’s Generics: Part 1” for examples of inheriting from a generic class causing weirdness.)

Happy swifting…

Private: It’s Not What You Think

So, here is an interesting tidbit for any of you Swifters that have experience in other languages with access modifiers: “private” doesn’t mean what you assume it means.

Put these to classes in the same file:

public class Secrets {
    private var shhh = "Cannot Hide"
}

public class Exposed : Secrets {
    public func CannotRun() -> String {
        return self.shhh // no compiler error?!
    }
}

 
And, call this:

// This has to be in the same file as the classes
Secrets().shhh // no compiler error?! value is "Cannot Hide"

// This, of course, can be put in a different file
Exposed().CannotRun() // returns "Cannot Hide"

 

Ok. That wasn’t what I was expecting. However, if we read the manual, we find the following: Private access restricts the use of an entity to its own defining source file. Use private access to hide the implementation details of a specific piece of functionality.

I have to admit that I didn’t discover this by reading Apple’s documentation. Actually, it happened by accident when I was playing in a playground. The thing about a playground is that it is just one file, which means that the “private” access modifier has no effect. So, when I made a class field private and was still able to access it, I assumed that there must be a bug in the playground. A quick search on Google straightened me out, though.

So, the next question I asked was “Why?” Why would you want “private” to scope variables, methods, and classes to the current file?

It just so happened that I needed a way to quickly create some fake instances of classes for testing. One of the requirements was that the faked instances should have unique IDs. Prior to Swift 1.2, the “static” keyword wasn’t available, so I came up with the following solution instead:

// UniqueItem.swift file

public class UniqueItem {
    public var id : Int
    
    init() {
        id = 0 // maps to unique database value
    }
}
// FakeUniqueItem.swift file

private var autoId: Int = 0

private func getNextId() -> Int {
    return autoId++
}

public class FakeUniqueItem : UniqueItem {
    override init(){
        super.init()
        id = getNextId()
    }
}
// MyTests.swift file
 
println(FakeUniqueItem().id) // 0
println(FakeUniqueItem().id) // 1
println(FakeUniqueItem().id) // 2

No “static”? No problem. Because both the autoId variable and getNextId() function were private, they weren’t accessible outside the file. I got the effect of a static variable because I was sharing the instance of autoId across instances of my FakeUniqueItem class.

Fortunately, the release of Swift 1.2 added static variables to the mix, so I was able to get rid of my global, private variable and function:

public class FakeUniqueItem : UniqueItem {
    private static var autoId : Int = 0
    
    override init(){
        super.init()
        id = FakeUniqueItem.autoId++
    }
}

So there you have it. My story of how I discovered what “private” means to Swift. If you can think of other ways to leverage it, please leave a comment!

Exploring Swift’s Generics: Part 1

I think using magic for my generics examples captures the mystical aura that surrounds Swift’s generic capabilities. Some of the behaviors are very different than what I’m used to seeing in other languages.

Let’s build some context.

Define a base class for magic:

class Magic {
    func cast() -> String {
        return ""
    }
}

 
Define base classes for different categories of magic:

class BlackMagic: Magic {
    override func cast() -> String {
        return ""
    }
}

class WhiteMagic: Magic {
    override func cast() -> String {
        return ""
    }
}

 
Implement some black magic:

class Fire: BlackMagic {
    override func cast() -> String {
        return "Fire!"
    }
}

class Ice: BlackMagic {
    override func cast() -> String {
        return "Ice!"
    }
}

 
Implement some white magic:

class Cure: WhiteMagic {
    override func cast() -> String {
        return "Cure!"
    }
}

class Antidote: WhiteMagic {
    override func cast() -> String {
        return "Antidote!"
    }
}

 
And, finally, define a magic user:

class Mage<T: Magic> {
    
    func castAll(items: [T]) {
        for item in items {
            println(item.cast())
        }
    }
}

 

Now that we have plenty of boiler plate code, let’s look at something a little more interesting. I want to create a mage that can only cast black magic. My initial thought was to do something like this:

class BlackMage : Mage<BlackMagic> { }

 
Unfortunately, in Swift this causes the following error: “classes derived from generic classes must also be generic” Hrm…

You may be thinking that creating the BlackMage class isn’t necessary. After all, we can just specify the type when we create our variable:

var blackMage = Mage<BlackMagic>()

 
But, for the sake of argument, let’s assume that I want to have functions on my BlackMage class that aren’t on my WhiteMage class and vice versa.

So, it is required that classes derived from a generic class also be generic classes. Can I assume that the generic type for my derived class is related to the base class’s generic type? Nope.

class MeaningOfLife {
    func answer() -> Int { return 42 }
}

class BlackMage<T: MeaningOfLife> : Mage<BlackMagic> {
    func compute(meaningOfLife: T){
        meaningOfLife.answer()
    }
}

BlackMage<MeaningOfLife>().castAll([Fire(), Ice()])
BlackMage<MeaningOfLife>().compute(MeaningOfLife())

 
Why does a derived class have to be generic if it’s base class is generic (especially when the derived class’s generic type has nothing to do with the base classes generic type)? I don’t have a clue… If any knowledgeable readers of the blog would like to chime in, I’d be happy to learn something from them.

The takeaway is this: when specifying a generic type for a class that derives from another generic, the specified type has no impact on the base class–it only specifies the type for generics in the derived class.

You may be wondering why I didn’t use protocols for Magic, BlackMagic, and WhiteMagic. It seems that using protocols also has some interesting effects on generics, but I’m going to save that for another post.