Swift 所需初始化的访问控制

Swift 所需初始化的访问控制,swift,access-control,initializer,Swift,Access Control,Initializer,必需的初始值设定项的访问控制规则似乎与未指定必需的规则不同。为什么? public class A { // required init() must be public, why? public required init() { } } public class B { // init() does not need to be public, why? init() { } } 首先,让我们把规则弄清楚。必需的初始值设定项不需要标记为公共。只要求required初始值设

必需的初始值设定项的访问控制规则似乎与未指定必需的规则不同。为什么?

public class A {
  // required init() must be public, why?
  public required init() { }
}

public class B {
  // init() does not need to be public, why?
  init() { }
}

首先,让我们把规则弄清楚。
必需的
初始值设定项不需要标记为
公共
。只要求
required
初始值设定项与类一样可访问。如果您的类是
public
,则它所需的初始值设定项也必须是
public
。如果您的类是
内部的
,则其所需的初始值设定项也必须是
内部的
(从技术上讲,您可以将其设置为
公共的
,但这样做毫无意义,并且会生成警告)。当然,如果您的类是
private
,那么所需的初始值设定项也应该是
private


那么,为什么呢? 这里有两个原因,但它们需要了解
required
关键字实际在做什么


首先,
required
关键字保证这个类及其所有子类实现这个特定的初始值设定项。使初始值设定项成为必需的一个主要原因是协议一致性,最常见的例子是
NSCoding
,它需要
init(编码者:)
初始值设定项。考虑到这一点,让我们考虑一个试图实现这个协议的类:

public class MySwiftClass: NSObject, NSCoding {
    // some implementations
    // including the two requirements of the NSCoding protocol
}

现在,试着用这个:

let mySwiftObject = MySwiftClass(coder: aCoder)
我们应该可以毫无问题地做到这一点,对吗?我的意思是,毕竟,
myswitclass
符合
NSCoding
协议,并且
NSCoding
协议保证会有一个
init(coder:)
初始值设定项

但是,如果允许您将
init(coder:)
标记为比该类更低的访问级别,则会有一个可以看到该类的范围,但无法访问其所需的初始值设定项。。。因此,尽管知道该类符合带有必需初始值设定项的协议,或者是从带有必需初始值设定项的父类继承的,但我们还是无法调用该必需初始值设定项,因为在我们所处的范围内,它似乎不存在


第二个原因是子类化自身

让我们以父类为例:

public class ParentClass {
    required init() {}
}

我们希望零参数初始值设定项是必需的。这意味着,如果从父类继承了任何内容,则还必须确保实现了零参数初始值设定项。但是如果允许我们让所需的初始值设定项的作用域小于类本身,那么就有一个作用域,在这个作用域中我们可以看到类,但是我们看不到所需的初始值设定项,那么,在该范围内创建的子类如何能够知道它们必须实现一个必需的初始值设定项呢?

这里需要注意的是,这只是因为类本身被标记为
public
。如果类本身没有访问修饰符,并假定为默认的
内部
,则
必需的
初始值设定项也不需要访问修饰符。@nhgrif请看我答案中的粗体文本。所需的init仍然需要一个访问修饰符,该修饰符至少是
内部的
,这是默认值,因此我们可以忽略它。我不认为我的评论和你的答案有分歧@RMenke@nhgrif只是想澄清一下,不是正确的;)我被否决了。如果有人愿意解释我犯的错误,或者如何改进我的答案,我很乐意更新答案。不是我,对我来说很好。但是,经过无数次的编辑,我又一次把自己的答案弄糟了。我几乎要放弃这个问答了。这个问题绝对不值得被否决。我也不值得。所以我们应该在这方面真正改进。