Swift Protocols Question

Tags: objective-c ios

I’m still very much a Swift newbie.

The following example is contrived, but it accurately depicts the problem I’m trying to solve.

I have a protocol:

protocol Value: Equatable

A number of different structs conform to this protocol. Some of those structs also conform to this protocol:

protocol Smashable {
  func valueBySmashing OtherValue (value: Value) -> Value

My intent is absolutely clear —    valueBySmashingOtherValuemust return an object that conforms to the Value protocol.

However, I get this error:    Protocol 'Value' can only be used as a generic constraint because it has Self or associated type requirements.  

Okay. So I revise the Smashable protocol like this:

protocol Smashable {
  func valueBySmashing OtherValue <T>(value: T) -> T

That compiles. Cool.

So in a struct named    FooI add this:

func valueBySmashing OtherValue <T>(value: T) -> T {
  return Bar()

That’s right — Foo’s valueBy Smashing OtherValue returns a Bar. (Yes, this is contrived, but it distills the more-complex real-world code, which makes sense and is absolutely the right thing to do.)

Both conform to    Value.

But I get this error on the    return Bar()line:    'Bar' is not convertible to 'T'.  

At this point I don’t know what to do. Hence this blog post.

Objective-C version

I approach Swift exactly like an Objective-C coder — because I’ve been writing Objective-C for almost 15 years. Here’s the Objective-C version:

@protocol Value<NSObject>
@protocol Smashable<NSObject>
- (id<Value>)valueBy SmashingOtherValue: (id<Value>) otherValue;
Foomethod (    Fooand    Barboth conform to    Value):
- (id<Value>)valueBy SmashingOtherValue: (id<Value>) otherValue {
  return [[Bar alloc] init];

One possibility

I’m still thinking in Objective-C. It’s entirely likely that there’s a Swift-like design that hasn’t occurred to me. But what is it?

One simple possibility: don’t use protocols at all. Make a    Valuestruct that does everything the various Value-conforming structs currently do. The    Valuestruct would be littered with switch statements, which is ugly (and is usually a sign of poor design), but it would work.

This doesn’t seem Swift-like, though, given the    importance of protocols to Swift. And I can’t make myself do it.

There must be a better option.

What I don’t want to do is complain, a la Nabokov, that this new language can’t match the suppleness of my native language. I’d rather assume it’s just that I haven’t learned this new language well enough.

P.S. I’ll happily link to your blog post if you write up a solution.