为什么我必须在我的自定义RangeReplaceableCollection

时间:2018-04-13 12:36:01

标签: swift swift-protocols swift4.1

我目前正在尝试将自定义集合类型更新为Swift 4.1。 但是,当我遵守文档并实现CollectionRangeReplaceableCollection的所有要求时,Xcode仍然抱怨我的类型不符合RangeReplaceableCollection

Here's问题mcve(由Hamish慷慨提供,谢谢你:)

class Foo<Element : AnyObject> {
  required init() {}
  private var base: [Element] = []
}

extension Foo : Collection {
  typealias Index = Int

  var startIndex: Index {
    return base.startIndex
  }

  var endIndex: Index {
    return base.endIndex
  }

  func index(after i: Index) -> Index {
    return base.index(after: i)
  }

  subscript(index: Index) -> Element {
    return base[index]
  }
}

extension Foo : RangeReplaceableCollection {
  func replaceSubrange<C : Collection>(
    _ subrange: Range<Index>, with newElements: C
  ) where Element == C.Element {}
}

According to the documentation,代码应编译:

  

将RangeReplaceableCollection一致性添加到您的自定义中   集合,添加一个空的初始化程序和replaceSubrange(_:with :)   自定义类型的方法。 RangeReplaceableCollection提供   使用它的所有其他方法的默认实现   初始化器和方法。

不幸的是,它没有。相反,Xcode会发出以下错误消息:

// error: type 'Foo<Element>' does not conform to protocol 'RangeReplaceableCollection'
// extension Foo : RangeReplaceableCollection {
// ^
//   Swift.RangeReplaceableCollection:5:26: note: candidate has non-matching type '<Self, S> (contentsOf: S) -> ()' [with SubSequence = Foo<Element>.SubSequence]
//   public mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element
//                        ^
//   Swift.RangeReplaceableCollection:9:26: note: protocol requires function 'append(contentsOf:)' with type '<S> (contentsOf: S) -> ()'; do you want to add a stub?
//   public mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element
//   

为了确保文档中没有错误,我检查了the source code of Swift 4.1并在RangeReplaceableCollection.swift中找到了func append<S>(contentsOf newElements: S) where S: Sequence, Element == S.Element的默认实现,第442-452行:

@_inlineable
public mutating func append<S : Sequence>(contentsOf newElements: S) where S.Element == Element {
  let approximateCapacity = self.count + numericCast(newElements.underestimatedCount)
  self.reserveCapacity(approximateCapacity)
  for element in newElements {
    append(element)
  }
}

问题:

  • 为什么Xcode要求实现此功能,尽管提供了默认实现?
  • 如何让我的代码编译?

1 个答案:

答案 0 :(得分:3)

为什么Xcode要求实现此功能,尽管提供了默认实现?

这是由于Swift 4.1中引入的TypeChecker中的一个错误:
[SR-7429]: Cannot conform a non-final class to a protocol with a defaulted requirement with a generic placeholder constrained to an associated type

如何编译我的代码?

在修复bug之前,目前有三种方法可以让它编译。

  • 实现这两个功能:

    • required init<S : Sequence>(_ elements: S) where Element == S.Element {}
    • func append<S : Sequence>(contentsOf newElements: S) where Element == S.Element
  • 将课程标记为final

  • 将集合类型实现为struct。为此,必须删除required init() {}