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
}
}
我不想在 SpotifyTrack
中将 trackNumber
设为可选,因为我知道 SpotifyTracks 的价值将始终存在。有没有比重命名属性更优雅的解决方案?
你可以有第二个 属性 作为第一个的支持:
protocol Track {
var trackNumber: Int? { get }
}
struct SpotifyTrack {
var realTrackNumber: Int
}
extension SpotifyTrack: Track {
var trackNumber: Int? { self.realTrackNumber }
}
但是,我感觉这就是您所说的 "renaming":您不想那样做。然而,协议的 "instructions" 是固定的:如果不声明明确类型为 Int?
.
的 trackNumber
,就不能采用 Track
Objective-C 有 @optional
协议成员,这意味着你可以让 Track 声明 trackNumber
Int 但 @optional
,然后你可以在没有 [=11] 的情况下采用 Track =] 完全。但是如果你想利用它,这不能是一个结构。
一种方法可能是您有一个基本轨道协议,然后有一个扩展基本协议的第二个协议。例如
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
}
其他类型的轨道可以遵循基本轨道协议的不同扩展
希望对您有所帮助:)
除了重命名符合类型的冲突 属性 之外,您的问题没有优雅的解决方案。
Swift 不允许一个类型上存在 2 个同名的属性,即使它们的类型不同。另一方面,Int?
和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 }
}
当协议将 属性 声明为 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
}
}
我不想在 SpotifyTrack
中将 trackNumber
设为可选,因为我知道 SpotifyTracks 的价值将始终存在。有没有比重命名属性更优雅的解决方案?
你可以有第二个 属性 作为第一个的支持:
protocol Track {
var trackNumber: Int? { get }
}
struct SpotifyTrack {
var realTrackNumber: Int
}
extension SpotifyTrack: Track {
var trackNumber: Int? { self.realTrackNumber }
}
但是,我感觉这就是您所说的 "renaming":您不想那样做。然而,协议的 "instructions" 是固定的:如果不声明明确类型为 Int?
.
trackNumber
,就不能采用 Track
Objective-C 有 @optional
协议成员,这意味着你可以让 Track 声明 trackNumber
Int 但 @optional
,然后你可以在没有 [=11] 的情况下采用 Track =] 完全。但是如果你想利用它,这不能是一个结构。
一种方法可能是您有一个基本轨道协议,然后有一个扩展基本协议的第二个协议。例如
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
}
其他类型的轨道可以遵循基本轨道协议的不同扩展
希望对您有所帮助:)
除了重命名符合类型的冲突 属性 之外,您的问题没有优雅的解决方案。
Swift 不允许一个类型上存在 2 个同名的属性,即使它们的类型不同。另一方面,Int?
和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 }
}