为什么Swift中的公共类/结构需要显式的公共初始化器? [英] Why does a public class/struct in Swift require an explicit public initializer?

查看:167
本文介绍了为什么Swift中的公共类/结构需要显式的公共初始化器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在模块中考虑以下类(同样适用于结构):

Consider the follow class (equally applicable to a struct, as well) in a module:

public class Foo {
   public func bar() {
       // method body
   }
}

注意,它没有显式的初始化程序;这个例子不需要任何特殊的初始化.该类可能会公开给其他模块,因为它被标记为public.但是,当模块外的代码尝试对其进行初始化时,编译器会抱怨:

Note, it does not have an explicit initializer; this example doesn't need any special initialization. This class would be exposed to other modules because it is marked public. However, when code outside the module attempts to initialize it, the compiler complains:

let foo = Foo() // 'Foo' initializer is inaccessible due to 'internal' protection level

为了使编译器满意,我必须定义一个标记为public的显式空初始化程序:

In order to satisfy the compiler, I have to define an explicit empty initializer marked public:

public class Foo {
   public init() {
       // This initializer intentionally left empty
   }

   public func bar() {
       // do something useful
   }
}

为什么,如果该类是显式的public,我是否需要显式定义一个公共初始化程序?它不应该隐式地有一个公共的初始化器吗?

Why, if the class is explicitly public, do I need to explicitly define a public initializer? Shouldn't it implicitly have a public initializer?

有一个相关问题

There is a related question here, pertaining to unit testing, but I find it doesn't really get at the core of the design philosophy of what I find to be a surprising issue.

推荐答案

将类标记为公共不一定意味着开发人员希望公开初始化该类.例如,我经常编写只为我创建的基类,以便能够对其进行子类化.我给这些超类提供了internal初始化器,以便它们的子类可以访问它们,但外界不应该直接使用它们.例如,Foundation中的Operation没有可访问的初始化程序,但该类是公共的.它只是意味着要被子类化.在Objective-C中,这被视为抽象类.

Marking a class public does not necessarily imply that the developer wants the class to be initialized publicly. For example, I often write base classes that exist solely for me to be able to subclass them. I give these superclasses internal initializers so that their subclasses can access them, but those in the outside world shouldn't be using them directly. For example, Operation in Foundation has no accessible initializers, yet the class is public. It is simply meant to be subclassed. This is considered an abstract class in Objective-C.

由于Swift不包含对抽象类的显式支持,因此使类成为公共但没有公共初始化程序的行为基本上充当抽象类(除了每个函数必须在类本身或某些类中仍具有默认定义)协议扩展).

Since Swift doesn't contain explicit support for abstract classes, the act of making a class public but without public initializers basically serves as an abstract class (except each function must still have a default definition, either in the class itself or some protocol extension).

考虑到这一点,下面是一些Swift规则:

With this in mind, here are some Swift rules:

  • 如果您的班级被标记为private,则所有变量,初始值和函数将默认为private.
  • 如果您的班级被标记为internal(默认设置),publicopen,则所有变量,初始化和函数将默认为internal.
  • 子类的超类必须至少具有可访问性.
  • 在Objective-C中声明为public
  • 类和类成员将以open的形式导入Swift中,因为在Objective-C中没有这种区别.
  • If your class is marked private, all variables, inits, and functions will default to private.
  • If your class is marked internal (which is default), public, or open, all variables, inits, and functions will default to internal.
  • A subclass's superclass must be at least as accessible.
  • classes and class members declared public in Objective-C are imported into Swift as open, due to there being no such distinction in Objective-C.

第二个是您遇到的那个.默认的初始化是选择默认的internal,因为Swift要做的最后一件事就是将您的初始化公开为公共API,除非明确指示这样做.

That second one is the one you are running into. The default init is picking up the default internal because the last thing Swift wants to do is expose your init as public API unless it is explicitly instructed to do so.

注意:在我的测试中(至少在操场上),似乎引入了fileprivate:

Note: In my tests (at least in the playground), it seems that with the introduction of fileprivate:

  • 如果将一个类声明为privatefileprivate,则除非明确标注private,否则该类成员似乎默认为fileprivate.
  • If a class is declared private or fileprivate, it seems that class members default to fileprivate unless explicitly annotated private.

这篇关于为什么Swift中的公共类/结构需要显式的公共初始化器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆