swiftswift-protocols

swift protocol conformance when same property name is optional


When a protocol declares a property as optional and a concrete type declares it as non-optional, how can I make the concrete type conform to the protocol?

Here's the problem:

protocol Track {
    var trackNumber: Int? { get } // not all tracks have a track number
}

struct SpotifyTrack {
    let trackNumber: Int // all SpotifyTrack are guaranteed to have a track number
}

extension SpotifyTrack: Track {
    var trackNumber: Int? {
        return self.trackNumber // WARNING: All paths through this function will call itself
    }
}

I don't want to make trackNumber optional in SpotifyTrack because I know the value will always be there for SpotifyTracks. Are there are any solutions more elegant than just renaming the properties?


Solution

  • There is no elegant solution to your problem other than renaming the conflicting property on the conforming type.

    Swift doesn't allow 2 properties of the same name to exist on a type even if their types are different. On the other hand, Int? and Int are completely different types, so you cannot have trackNumber: Int fulfil the protocol requirement of trackNumber: Int?.

    The only solution (other than changing the type in either the protocol or the struct) is to rename the non-Optional property in SpotifyTrack and make an optional computed property of the same name returning the non-optional one.

    protocol Track {
        var trackNumber: Int? { get }
    }
    struct SpotifyTrack {
        private let _trackNumber: Int
    }
    extension SpotifyTrack: Track {
        var trackNumber: Int? { _trackNumber }
    }