所以在Apple文档中:
扩展中添加的任何类型成员具有与要扩展的原始类型中声明的类型成员相同的默认访问级别.如果扩展公共或内部类型,则添加的任何新类型成员都将具有内部的默认访问级别.
给出UIView扩展的子类:
extension UIViewSubClass { var helloWorld : String { get { return "helloWorld" } } }
这将标记helloWorld
为内部,我没有问题,我在基于Objective-C的项目中看不到它.
但是,如果我将扩展标记为公开:
public extension UIViewSubClass { var helloWorld : String { get { return "helloWorld" } } }
现在helloWorld
在我的基于Objective-C的代码中出现,这意味着它被标记为公共.
但是,我没有看到苹果提到这一点,做到了吗?
我刚看到文档说公共类仍然具有隐含的内部级别.
public class SomePublicClass { // explicitly public class public var somePublicProperty = 0 // explicitly public class member var someInternalProperty = 0 // implicitly internal class member private func somePrivateMethod() {} // explicitly private class member }
将公共扩展标记为扩展似乎与标记类定义具有不同的效果.这让我感到困惑.
有人可以帮助我,这应该是这样,还是这是一种快速的错误?我使用swift 2.1和Xcode 7.2
答案:是的,public
在扩展名前放置访问级别修饰符(在您的情况下,特别是)会修改该扩展范围内所有新类型的默认访问级别.
请注意,修饰符不会影响正在扩展的类/ struct/etc的访问级别(只有它的成员.但是,有些事情应该被考虑,我将在下面讨论.
在本次讨论中,我将发布一些关于Swift访问级别的重要事实.所有这些都来自Swift语言指南 - 访问控制 - 访问级别.
让我们首先确定您已经说过的内容:
如果您没有自己指定显式访问级别,则代码中的所有实体(具有一些特定的例外情况,如本章后面所述)都具有内部的默认访问级别 .
好的,这与你在问题中引用的内容一致:任何新的类型成员,无论是在类或结构定义中,都将具有内部的默认访问级别.
现在,让我们看一下您可以在扩展名前添加的访问级别修饰符:
您可以在类,结构或枚举可用的任何访问上下文中扩展类,结构或枚举.扩展中添加的任何类型成员具有与要扩展的原始类型中声明的类型成员相同的默认访问级别.如果扩展公共或内部类型,则添加的任何新类型成员都将具有内部的默认访问级别.如果扩展私有类型,则添加的任何新类型成员都将具有私有的默认访问级别.
或者,您可以使用显式访问级别修饰符(例如,专用扩展名)标记扩展,以为扩展中定义的所有成员设置新的默认访问级别.仍可以在单个类型成员的扩展中覆盖此新默认值.
这样可以解决问题.我们查看您的示例,并假设您的类UIViewSubClass
具有访问级别public
(或编译时错误,如下所示):
/* no access level modifier: default access level will be 'internal' */ extension UIViewSubClass { // default access level used: internal var helloWorld : String { get { return "helloWorld" } } } // modify default access level to public public extension UIViewSubClass { // default access level used: public var helloWorld : String { get { return "helloWorld" } } }
考虑到上面的讨论,我们希望helloWorld
您的public extension ...
内容internal
在此上下文中标记为默认访问级别.在扩展的上下文中,访问级别修饰符的工作方式与应用于类型时的工作方式不同.
最后,我们应该指出public
在扩展非公共类时使用访问修饰符将在Swift中产生编译时错误.所以在你的情况下:
如果UISubViewClass
是一个internal
或一个private
类,那么public extension ...
该类将产生编译时错误.
如果UISubViewClass
是一个public
类,那么添加public extension
将是多余的,因为根据定义,公共类的默认访问修饰符已经是public
.
我要说上面描述的错误并不是一个错误,以避免运行时错误,而是避免冗余(和混乱)代码:public
成员类型private
或internal
类永远不会使用它s
公共访问级别.
class MyImplicitlyInternalClass { private var myExplicitlyPrivateVar = 0 var myImplicitlyInternalVar = 0 public var myExplicitlyPublicVar = 0 // warning, see (Note 1) below // redundant 'public': can never be accessed publicly // myExplicitlyPublicVar will behave as 'internal' } public extension MyImplicitlyInternalClass { // error, see (Note 2) var myNewVarIsInternal : Int { get { return 0 } } } /* (Note 1) Compile type warning: "Declaring a public var for an internal class." (Note 2) Compile time error: "Extension of internal class cannot be declared public." Summary: in theory, these two above are the same type of 'faults', but only the latter is flagged as and error. */
因此,只有永远很有意义的使用访问级别修饰符的扩展使默认的访问级别更严格,即使用internal extension ...
一个的public
类或private extension
或internal
类.