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

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

我没有发现任何提到的访问修饰符在Swift参考。是否有可能限制Swift中数据的可见性?


当前回答

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

公共 内部 私人

这三点适用于类、协议、函数和属性。

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

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

其他回答

当人们谈论在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中为此目的使用的类扩展。

你可以使用的一个选项是将实例创建包装到一个函数中,并在构造函数中提供适当的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

使用协议、闭包和嵌套/内部类的组合,现在可以使用模块模式来隐藏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和mysterousmath隐藏在这里,不被外部使用,试图挖掘对象的方法应该会导致错误。

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

对于Swift 1-3:

不,不可能。这里根本没有任何私有/受保护的方法和变量。

一切都是公开的。

更新 从Swift 4开始,可能会在这个帖子中看到其他答案

从Xcode 6 beta 4开始,Swift就有了访问修饰符。发布说明如下:

Swift访问控制分为三种访问级别: 私有实体只能从定义它们的源文件中访问。 内部实体可以在目标中定义它们的任何地方访问。 公共实体可以从目标中的任何地方访问,也可以从导入当前目标模块的任何其他上下文访问。

隐式默认值是内部的,因此在应用程序目标中,您可以关闭访问修饰符,除非在需要更严格限制的地方。在框架目标中(例如,如果你嵌入一个框架来在应用程序和共享或Today视图扩展之间共享代码),使用public指定你想要向框架的客户端公开的API。