【问题标题】:Compiler doesn't recognize a method in a private extension as private编译器无法将私有扩展中的方法识别为私有
【发布时间】:2018-08-09 14:55:50
【问题描述】:

我有以下代码:

class C {
    private enum E {
        // ...
    }
}

private extension C {
    func f(e: E) {    // error: Method must be declared private because its parameter uses a private type
        // ...
    }
}

如果我创建错误方法private,编译器错误就会消失。我想知道这是 Swift 中的错误还是我没有得到任何东西?

【问题讨论】:

  • “因为它的参数使用私有类型”是相关部分。 E 是私有的,所以 f(E) 也需要私有
  • @WarrenBurton,我认为 OP 说 Swift 应该推断它是私有的,因此不需要额外的关键字。对吧,奥普?
  • @WarrenBurton 该方法位于private 扩展内,这也使其成为private。我错了吗?
  • @LinusGeffarth 绝对! :)

标签: swift


【解决方案1】:

在顶层,private 等价于 fileprivate——private 表示只能在封闭范围内访问(以及相同的文件扩展名),在顶层,文件 那个范围。

所以你这里的内容相当于:

class C {
    private enum E {
        // ...
    }
}

fileprivate extension C {
    // error: Method must be declared private because its parameter uses a private type.
    func f(e: E) { 
        // ...
    }
}

(出于这个原因,为了清楚起见,我总是在顶层写 fileprivate 而不是 private

这使得问题更容易理解——扩展方法f默认为fileprivate,因此可以在整个文件的范围内访问,但其参数类型为E,只能在类C的范围。

正如您所发现的,您可以将f 标记为private

class C {
  private enum E {
    // ...
  }
}

fileprivate extension C {
  private func f(e: E) {
    // ...
  }
}

或者将E标记为fileprivate

class C {
  fileprivate enum E {
    // ...
  }
}

fileprivate extension C {
  func f(e: E) {
    // ...
  }
}

为了解决问题,使扩展方法f 与其参数类型E 具有相同的可见性。

【讨论】:

  • Hamish,感谢您的研究和解释,非常有趣!因此,简而言之,您不会认为这种行为是错误,对吧?
  • @ArtemStepanenko 正确,它按预期工作,尽管不是立即显而易见。
  • @Hamish 你知道如何在 Swift 4 中将 RangeReplaceableCollection Index 限制为 BidirectionalIndexType 吗?
  • @LeoDabus 嗯,BidirectionalIndexType 来自 Swift 2 集合索引模型的日子,索引会自行移动。使用新的集合模型,对索引类型的唯一限制是它们必须是 Comparable(对于任何类型的集合)。
  • 我需要在扩展RangeReplaceableCollection stackoverflow.com/questions/52065329/…时访问last属性
猜你喜欢
  • 2013-05-20
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
  • 2013-07-02
  • 2014-11-22
  • 2017-05-23
  • 1970-01-01
  • 2011-12-06
相关资源
最近更新 更多