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

相同属性名称可选时的swift协议一致性,swift,swift-protocols,Swift,Swift Protocols,当协议将属性声明为可选而具体类型将其声明为非可选时,如何使具体类型符合协议 问题是: 协议跟踪{ var trackNumber:Int?{get}//并非所有曲目都有曲目编号 } 结构SpotifyTrack{ let trackNumber:Int//所有SpotifyTrack都保证有一个曲目编号 } 扩展轨迹:轨迹{ 变量trackNumber:Int{ return self.trackNumber//警告:通过此函数的所有路径都将调用自身 } } 我不想在SpotifyTrack中

当协议将属性声明为可选而具体类型将其声明为非可选时,如何使具体类型符合协议

问题是:

协议跟踪{
var trackNumber:Int?{get}//并非所有曲目都有曲目编号
}
结构SpotifyTrack{
let trackNumber:Int//所有SpotifyTrack都保证有一个曲目编号
}
扩展轨迹:轨迹{
变量trackNumber:Int{
return self.trackNumber//警告:通过此函数的所有路径都将调用自身
}
}

我不想在
SpotifyTrack
中选择
trackNumber
,因为我知道SpotifyTrack的值总是存在的。有没有比重命名属性更优雅的解决方案

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

protocol Track {
    var trackNumber: Int? { get }
}
struct SpotifyTrack {
    var realTrackNumber: Int
}
extension SpotifyTrack: Track {
    var trackNumber: Int? { self.realTrackNumber }
}
然而,我有一种感觉,那就是你所谓的“重命名”的意思:你宁愿不这样做。然而,协议的“说明”是明确的:如果不声明显式键入为
Int?
trackNumber
,就不能采用Track


Objective-C具有
@可选
协议成员,这意味着您可以使用Track declare
trackNumber
Int,但
@可选
,然后您可以采用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
}
然后,其他类型的轨道可以遵循基本轨道协议的不同扩展


希望它能有所帮助:)

除了重命名一致性类型上的冲突属性之外,您的问题没有优雅的解决方案

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

唯一的解决方案(除了更改
协议
结构
中的类型外)是重命名
SpotifyTrack
中的非可选属性,并使用相同名称的可选计算属性返回非可选属性

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

谢谢你的回答,但这确实是我所指的“重命名”财产;因为它会产生一个尴尬的名称(spotify曲目的曲目编号实际上不是“真实的”),所以这个惯例实际上就像David Pasztor建议的那样,使用下划线。我只是用“真实”来让人们更容易看到我在做什么尽管如此,他说的和我完全一样。然而,我回答的要点是,协议的规定是绝对决定性的。它告诉你为了通过协议你必须说些什么。所以,要么你们需要一个不同的协议(正如另一个答案所暗示的),要么你们必须接受“重命名”。或者什么都不做!可选解决方案不是重量级解决方案。