在Objective-C实例中,数据可以是公共的、受保护的或私有的。例如:

@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个访问级别,从最高(限制最少)到最低(限制最多)。


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

其他回答

现在在测试版4中,他们为Swift添加了访问修饰符。

from Xcode 6 beta 4 realese notes:

Swift access control has three access levels: private entities can only be accessed from within the source file where they are defined. internal entities can be accessed anywhere within the target where they are defined. public entities can be accessed from anywhere within the target and from any other context that imports the current target’s module. By default, most entities in a source file have internal access. This allows application developers to largely ignore access control while allowing framework developers full control over a framework's API.

语言语法没有关键字“public”,“private”或“protected”。这意味着一切都是公开的。当然,可以有一些替代方法来指定没有这些关键字的访问修饰符,但我在语言参考中找不到它。

从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

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

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

创建一个基类来保存“受保护的”方法(实际上是私有的) 子类化这个类以使用相同的方法 在其他文件中,您不能访问基类方法,即使您创建了子类

文件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或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中为此目的使用的类扩展。