繁体   English   中英

swift 协议一致性时相同的属性名称是可选的

[英]swift protocol conformance when same property name is optional

当协议将属性声明为optional而具体类型将其声明为non-optional时,如何使具体类型符合协议?

这是问题所在:

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
    }
}

我不想让trackNumber中的SpotifyTrack成为可选,因为我知道 SpotifyTracks 的价值将永远存在。 有没有比仅仅重命名属性更优雅的解决方案?

除了重命名符合类型的冲突属性之外,没有优雅的解决方案可以解决您的问题。

Swift 不允许在一个类型上存在两个同名的属性,即使它们的类型不同。 另一方面, Int? Int是完全不同的类型,所以你不能让trackNumber: Int满足 trackNumber: Int 的协议要求trackNumber: Int? .

唯一的解决方案(除了更改protocolstruct中的类型)是重命名SpotifyTrack中的非可选属性,并创建一个同名的可选计算属性,返回非可选属性。

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

您可以拥有第二个属性作为第一个属性的支持:

protocol Track {
    var trackNumber: Int? { get }
}
struct SpotifyTrack {
    var realTrackNumber: Int
}
extension SpotifyTrack: Track {
    var trackNumber: Int? { self.realTrackNumber }
}

但是,我有一种感觉,这就是您所说的“重命名”:您宁愿不这样做。 然而,协议的“指令”是坚定的:如果不声明明确类型为Int?trackNumber ,就不能采用 Track? .

Objective-C 具有@optional协议成员,这意味着您可以让 Track 声明trackNumber Int 但@optional ,然后您可以采用 Track根本没有trackNumber 但是如果你想利用它,这不可能是一个结构。

一种方法可能是你有一个基本跟踪协议,然后有一个扩展基本协议的第二个协议。 例如

protocol BaseTrackProtocol {
    var title:String
    var artist:String
}

protocol SpotifyTrackProtocol : BaseTrackProtocol {
    var trackNumber:Int
}

struct SoptifyTrack: SpotifyTrackProtocol {
    var title:String
    var artist:String
    var trackNumber:Int
}

然后其他类型的轨道可以遵循基本轨道协议的不同扩展

希望能帮助到你:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM