Swift有访问修饰符吗?

在Objective-C实例中,数据可以是publicprotectedprivate 。 例如:

 @interface Foo : NSObject { @public int x; @protected: int y; @private: int z; } -(int) apple; -(int) pear; -(int) banana; @end 

我没有发现在Swift引用中提及访问修饰符。 是否有可能限制数据在Swift中的可见性?

Swift 3.0.1开始 ,有4个访问级别,从最高(限制最less)到最低(限制最多)描述如下。


1. openpublic

使实体能够在定义模块(目标)之外使用。 在为框架指定公共接口时,通常使用openpublic访问。

但是, open访问仅适用于class级和class级成员 ,与public访问不同,具体如下:

  • public类和类成员只能在定义模块(目标)中被分类和覆盖。
  • open类和类成员可以在定义模块(目标)之内和之外被分类和覆盖。
 // First.framework – A.swift open class A {} 
 // First.framework – B.swift public class B: A {} // ok 
 // Second.framework – C.swift import First internal class C: A {} // ok 
 // Second.framework – D.swift import First internal class D: B {} // error: B cannot be subclassed 

2. internal

允许在定义模块(目标)内使用实体。 定义应用程序或框架的内部结构时,通常使用internal访问。

 // First.framework – A.swift internal struct A {} 
 // First.framework – B.swift A() // ok 
 // Second.framework – C.swift import First A() // error: A is unavailable 

3. fileprivate

限制使用实体到其定义的源文件。 当在整个文件中使用这些细节时,通常使用fileprivate访问来隐藏特定function部分的实现细节。

 // First.framework – A.swift internal struct A { fileprivate static let x: Int } Ax // ok 
 // First.framework – B.swift Ax // error: x is not available 

4. private

限制对附属声明使用实体。 当这些细节仅在单个声明中使用时,您通常使用private访问来隐藏特定function的实现细节。

 // First.framework – A.swift internal struct A { private static let x: Int internal static func doSomethingWithX() { x // ok } } Ax // error: x is unavailable 

当谈到在Swift或者ObjC(或者ruby,java或者…)中使用“私有方法”时,这些方法并不是真正的私有方法。 他们周围没有实际的访问控制。 任何能够提供一点反思的语言都可以让开发人员在真正需要的时候从课外获得这些价值。

所以我们在这里所讨论的是一种定义一个面向公众的界面的方法,它只是呈现我们想要的function,而“隐藏”我们认为是“私人”的其余部分。

Swift声明接口的机制是protocol ,可以用于这个目的。

 protocol MyClass { var publicProperty:Int {get set} func publicMethod(foo:String)->String } class MyClassImplementation : MyClass { var publicProperty:Int = 5 var privateProperty:Int = 8 func publicMethod(foo:String)->String{ return privateMethod(foo) } func privateMethod(foo:String)->String{ return "Hello \(foo)" } } 

请记住,协议是一stream的types,可以在任何types的地方使用。 而且 ,这样使用时,他们只暴露自己的接口,而不是实现types的接口。

因此,只要你在参数types中使用MyClass而不是MyClassImplementation等,它应该都是正常的:

 func breakingAndEntering(foo:MyClass)->String{ return foo.privateMethod() //ERROR: 'MyClass' does not have a member named 'privateMethod' } 

有一些直接分配的情况下,你必须明确的types,而不是依靠Swift来推断它,但这似乎不是一个交易断路器:

 var myClass:MyClass = MyClassImplementation() 

这样使用协议是语义的,合理的简洁,而且我的眼睛看起来很像我们在ObjC中用于这个目的的类扩展。

据我所知,没有关键字“公共”,“私人”或“保护”。 这表明一切都是公开的。

然而,苹果可能期望人们使用“ 协议 ”(世界其他地方称为接口)和工厂devise模式来隐藏实现types的细节。

无论如何,这通常是一个好的devise模式。 因为它可以让你改变你的实现类层次结构,同时保持逻辑types系统相同。

使用协议,闭包和嵌套/内部类的组合,可以沿着模块模式的行使用某些东西来隐藏Swift中的信息。 它不是超级干净或不错的阅读,但它确实工作。

例:

 protocol HuhThing { var huh: Int { get set } } func HuhMaker() -> HuhThing { class InnerHuh: HuhThing { var innerVal: Int = 0 var huh: Int { get { return mysteriousMath(innerVal) } set { innerVal = newValue / 2 } } func mysteriousMath(number: Int) -> Int { return number * 3 + 2 } } return InnerHuh() } HuhMaker() var h = HuhMaker() h.huh // 2 h.huh = 32 h.huh // 50 h.huh = 39 h.huh // 59 

innerVal和mysteriousMath从外部使用隐藏在这里,并试图挖掘到对象的方式应该导致错误。

我只是通过阅读Swift文档的一部分,所以如果在这里有一个缺陷,请指出,很想知道。

从Xcode 6 beta 4开始,Swift有访问修饰符。 从发行说明:

Swift访问控制有三个访问级别:

  • 私人实体只能从定义它们的源文件中访问。
  • 内部实体可以在定义目标的任何地方访问。
  • 公共实体可以从目标中的任何地方以及导入当前目标模块的任何其他上下文访问。

隐式默认是internal ,所以在应用程序目标中,除了要限制的地方以外,您可以closures访问修饰符。 在框架目标中(例如,如果您embedded框架以在应用程序和共享或“今日”视图扩展之间共享代码),请使用public来指定您要公开给框架客户端的API。

斯威夫特4

正如Swift文档 – 访问控制所提到的, Swift 45个访问控制

  • 开放公开 :可以从他们的模块的实体和任何导入定义模块的模块实体进行访问。

  • 内部 :只能从模块的实体访问。 这是默认的访问级别。

  • fileprivateprivate :只能在您定义的有限范围内进行限制访问。


公开公共有什么区别?

open与以前版本的Swift中的public相同,它们允许其他模块的类使用并inheritance它们,即:它们可以从其他模块中分类。 而且,它们允许其他模块的成员使用并覆盖它们。 相同的逻辑适用于他们的模块。

public允许来自其他模块的类使用它们,但不能inheritance它们,即:它们不能从其他模块中inheritance。 而且,它们允许其他模块的成员使用它们,但不能覆盖它们。 对于他们的模块,它们具有相同的开放逻辑(它们允许类使用并inheritance它们;它们允许成员使用并覆盖它们)。

fileprivateprivate有什么区别?

fileprivate可以从他们的整个文件中访问。

私人只能从他们的单个声明和同一个文件中声明的扩展中访问; 例如:

 // Declaring "A" class that has the two types of "private" and "fileprivate": class A { private var aPrivate: String? fileprivate var aFileprivate: String? func accessMySelf() { // this works fine self.aPrivate = "" self.aFileprivate = "" } } // Declaring "B" for checking the abiltiy of accessing "A" class: class B { func accessA() { // create an instance of "A" class let aObject = A() // Error! this is NOT accessable... aObject.aPrivate = "I CANNOT set a value for it!" // this works fine aObject.aFileprivate = "I CAN set a value for it!" } } 

Swift 3和Swift 4 Access Control之间有什么区别?

正如在SE-0169提案中所提到的那样,Swift 4中唯一的改进就是私有访问控制范围已经扩展到可以在同一个文件中从该声明的扩展中访问; 例如:

 struct MyStruct { private let myMessage = "Hello World" } extension MyStruct { func printMyMessage() { print(myMessage) // In Swift 3, you will get a compile time error: // error: 'myMessage' is inaccessible due to 'private' protection level // In Swift 4 it should works fine! } } 

所以,没有必要声明myMessage作为fileprivate在整个文件中可访问。

补充说明:如果您遇到与未编译Swift 4和Swift 3项目相关的问题,可以查看这个问题解答 。

Swift 3.0提供了五种不同的访问控制:

  1. 打开
  2. 上市
  3. 内部
  4. fileprivate
  5. 私人的

开放访问和公共访问使实体能够在来自其定义模块的任何源文件中使用,并且也可以来自导入定义模块的另一个模块的源文件。 在为框架指定公共接口时,通常使用开放或公共访问。

内部访问使实体能够在其定义模块的任何源文件中使用,但不能在该模块之外的任何源文件中使用。 定义应用程序或框架的内部结构时,通常使用内部访问。

文件私有访问将实体的使用限制在自己定义的源文件中。 当在整个文件中使用这些细节时,使用文件私有访问来隐藏特定function的实现细节。

私人访问限制了实体对封闭声明的使用。 当这些细节仅在一个声明中使用时,使用私有访问来隐藏特定function的实现细节。

开放访问是最高(限制最less)的访问级别, 私有访问是最低(限制最多)的访问级别。

默认访问级别

如果您没有自己指定明确的访问级别,那么代码中的所有实体(具有一些特定的例外)都具有默认的内部访问级别。 因此,在许多情况下,您不需要在代码中指定明确的访问级别。

关于该主题的发行说明:

声明为public的类不能再在其定义模块之外进行子类化,并且声明为public的方法不能再在其定义模块之外被覆盖。 为了让一个class级在外部进行分类,或者是一个外部超越的方法,可以宣布这个class级是开放的,这是一个超越公众的新的访问级别。 导入的Objective-C类和方法现在全部导入为公开而不是公开的。 使用@testable导入导入模块的unit testing仍然可以inheritance公共或内部类,也可以覆盖公共或内部方法。 (SE-0117)

更多信息和细节: Swift编程语言(访问控制)

在Beta 6中,文档指出有三种不同的访问修饰符:

  • 上市
  • 内部
  • 私人的

这三个适用于类,协议,function和属性。

 public var somePublicVariable = 0 internal let someInternalConstant = 0 private func somePrivateFunction() {} 

有关更多信息,请检查访问控制

不,这是不可能的。 没有任何私有/受保护的方法和variables。

一切都是公开的。

Xcode 6引入的访问控制机制:

Swift为代码中的实体提供了三种不同的访问级别。 这些访问级别与实体定义的源文件相关,也与源文件所属的模块有关。

  • 公共访问使得实体可以在来自定义模块的任何源文件中使用,也可以在来自导入定义模块的另一个模块的源文件中使用。 在为框架指定公共接口时,通常使用公共访问。
  • 内部访问使实体能够在其定义模块的任何源文件中使用,但不能在该模块之外的任何源文件中使用。 定义应用程序或框架的内部结构时,通常使用内部访问。
  • 私人访问限制了一个实体对自己的定义源文件的使用。 使用私人访问来隐藏特定function的实现细节。

公共访问是最高(限制最less)的访问级别,私有访问是最低(或限制最多)的访问级别。

默认encryption内部 ,不需要指定。 另请注意, 私有说明符在类级别上不起作用,但在源文件级别上。 这意味着为了让一个类的一部分真的是私有的,你需要将它们分离成一个自己的文件。 这也介绍了一些有关unit testing的有趣案例。

在上面的链接中对我的另一个观点是,你不能'升级'访问级别。 如果你inheritance了一些东西,你可以更多地限制它,但不能反其道而行之。

这最后一点还影响到函数,元组和其他东西,即如果一个函数使用一个私有类,那么这个函数是内部的还是公共的是无效的,因为它们可能无法访问私有类。 这会导致编译器警告,您需要将该函数重新声明为私有函数。

您可以使用的一个选项是将实例创build包装到一个函数中,并在构造函数中提供相应的getter和setter:

 class Counter { let inc: () -> Int let dec: () -> Int init(start: Int) { var n = start inc = { ++n } dec = { --n } } } let c = Counter(start: 10) c.inc() // 11 c.inc() // 12 c.dec() // 11 

现在在testing版4中,他们已经为Swift添加了访问修饰符。

来自Xcode 6 beta 4的官方说明 :

Swift访问控制有三个访问级别:

  • private实体只能从它们被定义的源文件中访问。
  • internal实体可以在他们定义的目标内的任何地方访问。
  • public实体可以从目标中的任何地方以及导入当前目标模块的任何其他上下文访问。

默认情况下,源文件中的大多数实体都具有内部访问权限。 这允许应用程序开发人员很大程度上忽略访问控制,同时允许框架开发人员完全控制框架的API。

Swift 3和4也为variables和方法的访问级别带来了很多变化。 Swift 3和4现在有4个不同的访问级别,其中开放/公共访问级别最高(限制最less)访问级别, 私有访问级别最低(限制最多)访问级别:

  • 私有函数和成员只能在实体本身(struct,class,…)及其扩展(在Swift 3中,扩展受到限制)的范围内访问,
  • fileprivate函数和成员只能从它们声明的源文件中访问。
  • 内部函数和成员(默认情况下,如果不明确添加访问级别关键字)可以在定义目标的任何地方访问。 这就是为什么TestTarget没有自动访问所有的来源,他们必须在xCode的文件检查器中被标记为可访问。
  • 开放或公共职能和成员可以从目标中的任何地方以及导入当前目标模块的任何其他上下文访问。

有趣:

不要将每一个方法或成员都标记为“私有”,你可以在一个类/结构的扩展中覆盖一些方法(例如,通常是帮助函数),并将整个扩展标记为“私有”。

 class foo { } private extension foo { func somePrivateHelperFunction01() { } func somePrivateHelperFunction02() { } func somePrivateHelperFunction03() { } } 

这可能是一个好主意,为了获得更好的可维护代码。 你可以很容易地通过改变一个单词来切换(比如unit testing)非私有的。

苹果文档

语言语法不包含关键字'public','private'或'protected'。 这表明一切都是公开的。 当然,可能有一些替代的方法来指定没有这些关键字的访问修饰符,但我无法在语言参考中find它。

希望为那些想要类似于受保护方法的人节省一些时间:

根据其他答案,swift现在提供了“私有”修饰符 – 这是定义文件而不是类,如在Java或C#中的例如。 这意味着如果你想要受保护的方法,你可以使用swift私有方法, 如果它们在同一个文件中

  1. 创build一个基类来保存“受保护的”方法(实际上是私有的)
  2. 子类这个类使用相同的方法
  3. 在其他文件中,即使在子类中也不能访问基类方法

例如文件1:

 class BaseClass { private func protectedMethod() { } } class SubClass : BaseClass { func publicMethod() { self.protectedMethod() //this is ok as they are in same file } } 

文件2:

 func test() { var a = BaseClass() a.protectedMethod() //ERROR var b = SubClass() b.protectedMethod() //ERROR } class SubClass2 : BaseClass { func publicMethod() { self.protectedMethod() //ERROR } 

}

直到swift 2.0只有三个访问级别[公共,内部,私人],但在迅速3.0苹果增加了两个新的访问级别[Open,fileType]所以现在在3.0快速3.0有5访问级别在这里,我想清除angular色这两个访问级别1.开放:这是非常类似于公共,但唯一的区别是公众可以访问子类和覆盖,而开放访问级别不能访问该图像取自中等网站,这描述了差异在开放和公共访问之间

现在到第二个新的访问级别2.文件types是私人或更less的访问级别比内部更大的版本fileType可以访问[类,结构,枚举]的扩展部分和私人不能访问扩展部分的代码,它只能访问这个图像的词汇范围取自中等网站,这描述了fileType和Private访问级别之间的区别