Does Swift have access modifiers?

2019-01-02 19:45发布

In Objective-C instance data can be public, protected or private. For example:

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

I haven't found any mention of access modifiers in the Swift reference. Is it possible to limit the visibility of data in Swift?

17条回答
初与友歌
2楼-- · 2019-01-02 19:57

The language grammar does not have the keywords 'public', 'private' or 'protected'. This would suggest everything is public. Of course, there could be some alternative method of specifying access modifiers without those keywords but I couldn't find it in the language reference.

查看更多
心情的温度
3楼-- · 2019-01-02 19:58

When one talks about making a "private method" in Swift or ObjC (or ruby or java or…) those methods aren't really private. There's no actual access control around them. Any language that offers even a little introspection lets developers get to those values from outside the class if they really want to.

So what we're really talking about here is a way to define a public-facing interface that merely presents the functionality we want it to, and "hides" the rest that we consider "private".

The Swift mechanism for declaring interfaces is the protocol, and it can be used for this purpose.

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)"
  }
}

Remember, protocols are first-class types and can be used anyplace a type can. And, when used this way, they only expose their own interfaces, not those of the implementing type.

Thus, as long as you use MyClass instead of MyClassImplementation in your parameter types, etc. it should all just work:

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

There are some cases of direct assignment where you have to be explicit with type instead of relying on Swift to infer it, but that hardly seems a deal breaker:

var myClass:MyClass = MyClassImplementation()

Using protocols this way is semantic, reasonably concise, and to my eyes looks a lot like the Class Extentions we've been using for this purpose in ObjC.

查看更多
怪性笑人.
4楼-- · 2019-01-02 19:58

Hopefully to save some time for those who want something akin to protected methods:

As per other answers, swift now provides the 'private' modifier - which is defined file-wise rather than class-wise such as those in Java or C# for instance. This means that if you want protected methods, you can do it with swift private methods if they are in the same file

  1. Create a base class to hold 'protected' methods (actually private)
  2. Subclass this class to use the same methods
  3. In other files you cannot access the base class methods, even when you subclass either

e.g. File 1:

class BaseClass {
    private func protectedMethod() {

    }
}

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

File 2:

func test() {
    var a = BaseClass()
    a.protectedMethod() //ERROR


    var b = SubClass()
    b.protectedMethod() //ERROR
}

class SubClass2 : BaseClass {
    func publicMethod() {
        self.protectedMethod() //ERROR
    }

}

查看更多
琉璃瓶的回忆
5楼-- · 2019-01-02 19:59

In Beta 6, the documentation states that there are three different access modifiers:

  • Public
  • Internal
  • Private

And these three apply to Classes, Protocols, functions and properties.

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

For more, check Access Control.

查看更多
美炸的是我
6楼-- · 2019-01-02 19:59

Now in beta 4, they've added access modifiers to 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.

查看更多
回忆,回不去的记忆
7楼-- · 2019-01-02 20:02

Access control mechanisms as introduced in 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.

Default accecss it internal, and does as such not need to be specified. Also note that the private specifier does not work on the class level, but on the source file level. This means that to get parts of a class really private you need to separate into a file of its own. This also introduces some interesting cases with regards to unit testing...

Another point to me made, which is commented upon in the link above, is that you can't 'upgrade' the access level. If you subclass something, you can restrict it more, but not the other way around.

This last bit also affects functions, tuples and surely other stuff in the way that if i.e. a function uses a private class, then it's not valid to have the function internal or public, as they might not have access to the private class. This results in a compiler warning, and you need to redeclare the function as a private function.

查看更多
登录 后发表回答