【问题标题】:Access levels of custom initializers in Swift 3.1Swift 3.1 中自定义初始化器的访问级别
【发布时间】:2017-07-12 00:34:47
【问题描述】:

引自Swift 编程语言(Swift 3.1)

可以为自定义初始化程序分配小于或等于它们初始化的类型的访问级别。唯一的例外是必需的初始化程序(如必需初始化程序中所定义)。必需的初始化程序必须与其所属的类具有相同的访问级别。

如果是这样,为什么这段代码可以编译和工作?

private class GoofyClass {
    public init(mood: String) {}
    public required init(isCrazy: Bool) {}
}

private let shock = GoofyClass(mood: "shocked")
private let crazy = GoofyClass(isCrazy: true)

【问题讨论】:

  • 为什么不应该呢?没有超类,对吧?虽然声明为 public,但您有一个 init(isCrazy:) - 看起来不错 - 和第二个 init(mood:)。我能看到您遇到的唯一问题是您没有说明的问题 - 初始值是 public,类是 private。是的,我很惊讶它的构建(可能是 Xcode 8.3 编译器中的一个错误?),但我认为你不会轻易让你的应用程序在尝试初始化 private 类时崩溃。
  • 我在这里唯一的意思是 private 类和 public 初始化程序。这就是为什么我贴出书中的引文。 :)
  • 经过进一步调查,我发现协议的访问级别行为也与书中所述不同。它可能是一个错误的编译器。
  • 这是在游乐场吗?即使您将一个类声明为私有类,它仍然可以在同一个 Playground 文件中访问。
  • 是的,这是游乐场。我知道它可以在同一个文件中访问,但它是否解释了为什么编译器允许在内部声明更高的访问级别?

标签: swift swift3 xcode8 access-levels


【解决方案1】:

在 Swift 中,访问级别限制低于类/结构本身的类或结构的成员会自动降级到与类/结构相同的级别。我相信这是语言设计者深思熟虑的设计决定。

在您的情况下,假设该类在文件的顶层声明(即它没有嵌套在另一个类型中),那么您声明的 inits 实际上是 fileprivate

唯一的例外是必需的初始化程序(如必需初始化程序中所定义)。必需的初始化程序必须与其所属的类具有相同的访问级别。

这是指您不能使所需初始化程序的访问级别比其类限制更多,例如

open class Foo 
{
    internal required init() // error
}

【讨论】:

  • 我不认为显式声明是正确的。
  • @RoboRobok 事实上,在fileprivate 类中定义一个公共初始化器并不是一个错误。
  • 不过应该​​是,按照官书的说法。就像在较低访问级别的实体中定义具有较高访问级别的任何其他内容一样是错误的。
  • @RoboRobok 比较 Why am I allowed method access less restrictive than class access? - 能够定义具有比它们所定义的类型更高的访问级别的成员对于传达成员应该具有的访问级别非常有用更高的访问级别。正如 JeremyP 所说,这些成员仍然具有与类型的访问级别等效的有效访问级别。
  • @RoboRobok 如果这本书是这么说的,那本书就是错的。该行为在SE-0025 中定义,优先。(感谢您的参考,@Hamish)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
  • 1970-01-01
  • 2020-07-28
相关资源
最近更新 更多