【问题标题】:What is the `_base` property of an ReverseRandomAccessCollection?ReverseRandomAccessCollection 的 _base 属性是什么?
【发布时间】:2016-09-17 13:31:18
【问题描述】:

使用_base 属性访问ReverseRandomAccessCollection 的元素是一种好习惯吗?

let myArray = [1, 2, 3]
print(myArray.first) // returns 1

print(myArray.reversed().first) // returns 3
print(myArray.reversed()._base.first) // return 1, which is the underlying base array

【问题讨论】:

  • 我得到不同的结果:myReversedArray.first 返回 3,myReversedArray._base.first 返回 1。使用以下划线 (_) 开头的任何属性或方法时要非常小心。这些是未记录的,适用于编译器
  • 当你用myArray的反转版本初始化它时,为什么myReversedArray.first会返回1?
  • 抱歉各位,有错字,我更新了代码。
  • 我得到了相同的结果:1 3 1
  • 获取 1-3-1 复制和粘贴您自己的代码。你确定你运行的和你在这里展示的一样吗?什么版本的 Swift?

标签: arrays swift swift3


【解决方案1】:

ReverseRandomAccessCollection(你可以看到its full implementation here)是一个简单的包装器,它在底层RandomAccessCollection 上呈现一个反向的视图(这样就不必执行 O(n)穿过它)。

实现这一点的方法是通过保留底层集合的_base 属性,然后实现RandomAccessCollection 协议以便在其上呈现反向视图,例如反向索引遍历(cmets mine):

public struct ReversedRandomAccessCollection<
  Base : RandomAccessCollection
> : RandomAccessCollection {

    public let _base: Base // the underlying collection to present the reversed view on

    // ...

    public var startIndex: Index { // startIndex accesses endIndex of _base
        return ReversedRandomAccessIndex(_base.endIndex)
    }

    public var endIndex: Index { // endIndex accesses startIndex of _base
        return ReversedRandomAccessIndex(_base.startIndex)
    }

    public func index(after i: Index) -> Index { // index(after:) gets the index(before:)
        return ReversedRandomAccessIndex(_base.index(before: i.base))
    }

    public func index(before i: Index) -> Index { // index(before:) gets the index(after:)
        return ReversedRandomAccessIndex(_base.index(after: i.base))
    }

    public func index(_ i: Index, offsetBy n: IndexDistance) -> Index { 
        // index offset is simply made negative,
        // then forwarded to base's index(_:offsetBy:) method
        return ReversedRandomAccessIndex(_base.index(i.base, offsetBy: -n))
    }

    // ...
}

由于_base 属性是public,因此没有什么可以阻止您使用它。但是,下划线前缀的属性和方法用于表示不属于公共 API 的实现细节——因为它们通常不是为直接使用而设计的,并且可能会在没有警告的情况下进行更改。

在这种情况下,您可以在调用reversed() 之前简单地使用数组——它将与_base 相同(直到您对其进行变异)。因此,不要这样做:

myArray.reversed()._base.first

你应该这样做:

myArray.first

这将产生相同的结果。

【讨论】:

    【解决方案2】:

    正如 cmets 中提到的最好不要使用_ 方法,没有必要冒这种风险。在 Swift 3 中,reversed() 返回包装器 ReversedRandomAccessCollection 以访问数组,就好像它被颠倒了一样 - 无需 需要分配新数组,而 reverse() 会改变现有数组:

    var myArray = [1, 2, 3]
    myArray.reverse()
    print(myArray.first) // returns 3
    print(myArray.reversed().first) // returns 1
    print(myArray.reversed()._base.first) // return 3
    

    注意:您只能在var 上致电reverse()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-21
      • 2014-09-02
      • 2020-10-10
      • 2019-09-13
      • 2013-03-17
      • 2015-02-10
      • 2015-07-30
      • 2012-07-21
      相关资源
      最近更新 更多