在Objective-C实例中,数据可以是公共的、受保护的或私有的。例如:
@interface Foo : NSObject
{
@public
int x;
@protected:
int y;
@private:
int z;
}
-(int) apple;
-(int) pear;
-(int) banana;
@end
我没有发现任何提到的访问修饰符在Swift参考。是否有可能限制Swift中数据的可见性?
在Objective-C实例中,数据可以是公共的、受保护的或私有的。例如:
@interface Foo : NSObject
{
@public
int x;
@protected:
int y;
@private:
int z;
}
-(int) apple;
-(int) pear;
-(int) banana;
@end
我没有发现任何提到的访问修饰符在Swift参考。是否有可能限制Swift中数据的可见性?
当前回答
当人们谈论在Swift或ObjC(或ruby或java或…)中创建“私有方法”时,这些方法并不是真正的私有方法。他们周围没有实际的访问控制。任何语言只要能够提供一点内省功能,就可以让开发人员从类之外获得这些值,如果他们真的想要的话。
因此,我们在这里真正谈论的是一种定义面向公众的接口的方法,该接口仅呈现我们想要的功能,并“隐藏”其余我们认为是“私有”的功能。
Swift声明接口的机制就是协议,它可以用于此目的。
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)"
}
}
请记住,协议是第一类类型,可以在类型可以使用的任何地方使用。而且,当以这种方式使用时,它们只公开自己的接口,而不是实现类型的接口。
因此,只要你在参数类型中使用MyClass而不是MyClassImplementation,等等,它都应该工作:
func breakingAndEntering(foo:MyClass)->String{
return foo.privateMethod()
//ERROR: 'MyClass' does not have a member named 'privateMethod'
}
在一些直接赋值的情况下,你必须显式地使用类型,而不是依赖Swift来推断它,但这似乎并不是一个问题:
var myClass:MyClass = MyClassImplementation()
以这种方式使用协议是语义上的,相当简洁,而且在我看来很像我们在ObjC中为此目的使用的类扩展。
其他回答
从Swift 3.0.1开始,共有4个访问级别,从最高(限制最少)到最低(限制最多)。
1. 公开和公共
允许在定义模块(目标)之外使用一个实体。在指定框架的公共接口时,通常使用开放或公共访问。
然而,开放访问仅适用于类和类成员,它与公共访问的区别如下:
公共类和类成员只能在定义模块(目标)内进行子类化和重写。 开放类和类成员可以在定义模块(目标)内外被子类化和重写。
// 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. 内部
启用在定义模块(目标)中使用的实体。在定义应用程序或框架的内部结构时,通常使用内部访问。
// 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
将实体的使用限制到其定义的源文件。当在整个文件中使用特定功能块的实现细节时,通常使用文件私有访问来隐藏这些细节。
// First.framework – A.swift
internal struct A {
fileprivate static let x: Int
}
A.x // ok
// First.framework – B.swift
A.x // error: x is not available
4. 私人
将实体的使用限制在其封闭声明范围内。当只在单个声明中使用特定功能块的实现细节时,通常使用私有访问来隐藏这些细节。
// First.framework – A.swift
internal struct A {
private static let x: Int
internal static func doSomethingWithX() {
x // ok
}
}
A.x // error: x is unavailable
till swift 2.0 there were only three access level [Public, internal, private] but in swift 3.0 apple added two new access level which are [ Open, fileType ] so now in swift 3.0 there are 5 access level Here I want to clear the role of these two access level 1. Open: this is much similar to Public but the only difference is that the Public can access the subclass and override, and Open access level can not access that this image is taken from Medium website and this describe the difference between open and public access
现在是第二个新的访问级别 2. 文件类型是更大版本的私有或更低的访问级别比内部 fileType可以访问[class, struct, enum]的扩展部分 而且private不能访问扩展部分的代码,它只能访问 词法作用域 这张照片取自Medium网站,描述了fileType和Private访问级别之间的区别
当人们谈论在Swift或ObjC(或ruby或java或…)中创建“私有方法”时,这些方法并不是真正的私有方法。他们周围没有实际的访问控制。任何语言只要能够提供一点内省功能,就可以让开发人员从类之外获得这些值,如果他们真的想要的话。
因此,我们在这里真正谈论的是一种定义面向公众的接口的方法,该接口仅呈现我们想要的功能,并“隐藏”其余我们认为是“私有”的功能。
Swift声明接口的机制就是协议,它可以用于此目的。
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)"
}
}
请记住,协议是第一类类型,可以在类型可以使用的任何地方使用。而且,当以这种方式使用时,它们只公开自己的接口,而不是实现类型的接口。
因此,只要你在参数类型中使用MyClass而不是MyClassImplementation,等等,它都应该工作:
func breakingAndEntering(foo:MyClass)->String{
return foo.privateMethod()
//ERROR: 'MyClass' does not have a member named 'privateMethod'
}
在一些直接赋值的情况下,你必须显式地使用类型,而不是依赖Swift来推断它,但这似乎并不是一个问题:
var myClass:MyClass = MyClassImplementation()
以这种方式使用协议是语义上的,相当简洁,而且在我看来很像我们在ObjC中为此目的使用的类扩展。
Xcode 6中引入的访问控制机制:
Swift provides three different access levels for entities within your code. These access levels are relative to the source file in which an entity is defined, and also relative to the module that source file belongs to. Public access enables entities to be used within any source file from their defining module, and also in a source file from another module that imports the defining module. You typically use public access when specifying the public interface to a framework. Internal access enables entities to be used within any source file from their defining module, but not in any source file outside of that module. You typically use internal access when defining an app’s or a framework’s internal structure. Private access restricts the use of an entity to its own defining source file. Use private access to hide the implementation details of a specific piece of functionality. Public access is the highest (least restrictive) access level and private access is the lowest (or most restrictive) access level.
默认在内部访问,因此不需要指定。还要注意,私有说明符不是在类级别上工作,而是在源文件级别上工作。这意味着要使类的某些部分真正私有,您需要将其分离到自己的文件中。这也介绍了一些关于单元测试的有趣案例……
我提出的另一个观点(在上面的链接中有评论)是,你不能“升级”访问级别。如果你子类化了某个东西,你可以对它进行更多的限制,但反过来就不行。
最后一点也会影响函数、元组和其他东西,例如,如果一个函数使用了私有类,那么将函数设置为内部或公共是无效的,因为它们可能无法访问私有类。这将导致编译器警告,并且您需要将该函数重新声明为私有函数。
在Beta 6中,文档指出有三种不同的访问修饰符:
公共 内部 私人
这三点适用于类、协议、函数和属性。
public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}
有关更多信息,请检查访问控制。