[英]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?
.
唯一的解决方案(除了更改protocol
或struct
中的类型)是重命名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.