两个协议的协议类型约束
protocol type constraint by two protocols
我在下面设置了两个协议 swift 2
- 生成式(因为缺少更好的名称),它包含一组项目并提供类似数据源的功能,如计数和下标
public protocol Generative {
typealias GeneratedType
var elements: [GeneratedType] { get }
}
public extension Generative {
func count() -> Int {
return elements.count
}
subscript(index:Int) -> GeneratedType? {
if index >= count() {
return nil
}
return elements[index]
}
}
public protocol Selectable {
typealias SelectableType: Hashable
var selectedElements: Set<SelectableType> { get set }
}
extension Selectable {
public func isSelected(elem: SelectableType) -> Bool {
return selectedElements.contains(elem)
}
public mutating func addSelection(elem: SelectableType) {
selectedElements.insert(elem)
}
public mutating func removeSelection(elem: SelectableType) {
selectedElements.remove(elem)
}
public mutating func clearSelections() {
selectedElements.removeAll()
}
}
因此,如果一个对象同时实现了 Generative 和 Selectable,那么我希望它能够 return 选定的索引,所以我编写了这个函数:
func selectedIndices<S: Selectable where S: Generative, S.GeneratedType == S.SelectableType>(ds: S) -> [NSIndexPath] {
var selections: [NSIndexPath] {
return ds.selectedElements
.map{ (p: S.GeneratedType) -> NSIndexPath? in
if let idx = ds.elements.indexOf(p) { idx
return NSIndexPath(forRow: idx, inSection: 0)
}
return nil
}
.filter{ [=11=] != nil }
.map{ [=11=]! }
}
return selections
}
出于某种原因,链接器打印出:
Command failed due to signal: Segmentation fault: 11
不知道为什么,我想不出另一种方法来指定此函数以处理实现协议及其关联类型匹配的对象...
有什么想法吗?
P.S。 Gist 中的代码:https://gist.github.com/edwardIshaq/715b0e134fb47d2e28cc
-------- 更新
删除计算的 属性 似乎可以解决问题:
func selectedIndices<S: Selectable where S: Generative, S.GeneratedType == S.SelectableType>(ds: S) -> [NSIndexPath] {
return ds.selectedElements
.flatMap { (p: S.GeneratedType) -> NSIndexPath? in
if let idx = ds.elements.indexOf(p) { idx
return NSIndexPath(forRow: idx, inSection: 0)
}
return nil
}
}
编译器应该永远不会崩溃,但看起来原因更简单,似乎与在内部使用计算属性的泛型函数有关,这很简单:
// swiftc crashes when compiling this
func f<T>(t: T) -> Int {
var v: Int {
return 0
}
return v
}
因此,作为解决方法,请尝试重构代码以不使用计算的 属性。
你可以那样做,把它写成两个协议的扩展,像这样:
extension Selectable
where Self: Generative,
Self.GeneratedType == NSIndexPath,
Self.SelectableType == NSIndexPath
{
func selectedIndices() -> [NSIndexPath] {
return self.selectedElements.flatMap {
self.elements.indexOf([=11=]).map { NSIndexPath(index: [=11=]) }
}
}
}
我在下面设置了两个协议 swift 2
- 生成式(因为缺少更好的名称),它包含一组项目并提供类似数据源的功能,如计数和下标
public protocol Generative {
typealias GeneratedType
var elements: [GeneratedType] { get }
}
public extension Generative {
func count() -> Int {
return elements.count
}
subscript(index:Int) -> GeneratedType? {
if index >= count() {
return nil
}
return elements[index]
}
}
public protocol Selectable {
typealias SelectableType: Hashable
var selectedElements: Set<SelectableType> { get set }
}
extension Selectable {
public func isSelected(elem: SelectableType) -> Bool {
return selectedElements.contains(elem)
}
public mutating func addSelection(elem: SelectableType) {
selectedElements.insert(elem)
}
public mutating func removeSelection(elem: SelectableType) {
selectedElements.remove(elem)
}
public mutating func clearSelections() {
selectedElements.removeAll()
}
}
因此,如果一个对象同时实现了 Generative 和 Selectable,那么我希望它能够 return 选定的索引,所以我编写了这个函数:
func selectedIndices<S: Selectable where S: Generative, S.GeneratedType == S.SelectableType>(ds: S) -> [NSIndexPath] {
var selections: [NSIndexPath] {
return ds.selectedElements
.map{ (p: S.GeneratedType) -> NSIndexPath? in
if let idx = ds.elements.indexOf(p) { idx
return NSIndexPath(forRow: idx, inSection: 0)
}
return nil
}
.filter{ [=11=] != nil }
.map{ [=11=]! }
}
return selections
}
出于某种原因,链接器打印出:
Command failed due to signal: Segmentation fault: 11
不知道为什么,我想不出另一种方法来指定此函数以处理实现协议及其关联类型匹配的对象... 有什么想法吗?
P.S。 Gist 中的代码:https://gist.github.com/edwardIshaq/715b0e134fb47d2e28cc
-------- 更新 删除计算的 属性 似乎可以解决问题:
func selectedIndices<S: Selectable where S: Generative, S.GeneratedType == S.SelectableType>(ds: S) -> [NSIndexPath] {
return ds.selectedElements
.flatMap { (p: S.GeneratedType) -> NSIndexPath? in
if let idx = ds.elements.indexOf(p) { idx
return NSIndexPath(forRow: idx, inSection: 0)
}
return nil
}
}
编译器应该永远不会崩溃,但看起来原因更简单,似乎与在内部使用计算属性的泛型函数有关,这很简单:
// swiftc crashes when compiling this
func f<T>(t: T) -> Int {
var v: Int {
return 0
}
return v
}
因此,作为解决方法,请尝试重构代码以不使用计算的 属性。
你可以那样做,把它写成两个协议的扩展,像这样:
extension Selectable
where Self: Generative,
Self.GeneratedType == NSIndexPath,
Self.SelectableType == NSIndexPath
{
func selectedIndices() -> [NSIndexPath] {
return self.selectedElements.flatMap {
self.elements.indexOf([=11=]).map { NSIndexPath(index: [=11=]) }
}
}
}