首先要做的事情。因为我知道这是不可避免的,所以关于同一主题有一个similar question here。虽然话题是一样的, 其意图的推理/用法不同 。从而解决 问题与实现我在这里要求的内容不同。因此,请在将此标记为重复之前阅读我正在尝试解决的问题。谢谢!
在Swift中,我们使用与其他语言中的接口类似(但不完全相同)的协议。我在其他语言中看到的一件事,比如C#,是隐式和显式实现接口的能力。我想知道Swift是否具备后者的能力。
这是使用Swift语法显示的概念。注意这不会编译。这只是说明性的。
protocol DateSortable{
var sortDate:Date { get }
}
struct OrderedItem : DateSortable {
// Implicit conformance because the name sortDate matches the protocol
let sortDate:Date
}
struct Invoice : DateSortable {
let invoiceDate:Date
// Explicit conformance - Note you must specify the protocol name
// Additionally, you cannot access 'invoice.sortDate' directly
// You must cast to 'DateSortable' first
var DateSortable.sortDate:Date { return invoiceDate }
}
let someDate = orderedItem.sortDate // Allowed
let someOtherDate = invoice.sortDate // *NOT* Allowed
let antherDate = (invoice as! DateSortable).sortDate // Allowed
同样,上面是伪代码,但说明了其他语言如何支持此功能。
明确一致性的优点和好处
显式一致性的第一个优点是,您可以在不使自己的界面混乱的情况下符合协议。
例如,如果您有十个协议都定义了一个日期,它在功能上与您在模型中的日期匹配,但它们使用了十个不同的名称,显式一致性将允许您符合所有十个,而不具有在您的界面上公开展示这十个不同的名称。 (即上面,Invoice
只会直接公开invoiceDate
,即使它符合期望DateSortable
的{{1}}。)
第二个优点是它可以保护您免受成员命名冲突的影响。
考虑两个不相关的协议,例如sortDate
和Orderable
,但遗憾的是为其成员Deliverable
选择了相同的名称,并且它们不归您所有。他们正处于你正在使用的框架中。
现在,在您自己的var date:Date{ get }
模型中,您同时拥有PurchaseItem
和orderDate
。明确的一致性会解决这个问题,就像这样......
deliveryDate
简而言之,显式接口声明允许您按功能关联事物,而不是盲目地按名称关联。如果你愿意的话,你仍然可以通过名字将它们联系起来,因为这是自动的,但这不再是一个要求。
那么,Swift有没有与上面类似的东西?
关闭,但不完全!
我能提出的最接近的事情是私有扩展,在需要的网站上添加对该协议的一致性,就像这样......
extension PurchaseItem : Orderable {
var Orderable.date:Date { return orderDate }
}
extension PurchaseItem : Deliverable {
var Deliverable.date:Date { return deliveryDate }
}
但是,这种方法存在局限性和警告,as seen here。当然,这个问题的需求是不同的,但警告仍然是一样的。