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

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

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


当前回答

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

与其他答案一样,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 3.0提供了5种不同的访问控制:

开放 公共 内部 fileprivate 私人

Open access and public access enable 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 open or 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. File-private access restricts the use of an entity to its own defining source file. Use file-private access to hide the implementation details of a specific piece of functionality when those details are used within an entire file. Private access restricts the use of an entity to the enclosing declaration. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration. Open access is the highest (least restrictive) access level and private access is the lowest (most restrictive) access level.

默认访问级别

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

关于该主题的发布说明:

Classes declared as public can no longer be subclassed outside of their defining module, and methods declared as public can no longer be overridden outside of their defining module. To allow a class to be externally subclassed or a method to be externally overridden, declare them as open, which is a new access level beyond public. Imported Objective-C classes and methods are now all imported as open rather than public. Unit tests that import a module using an @testable import will still be allowed to subclass public or internal classes as well as override public or internal methods. (SE-0117)

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

Swift 4 / Swift 5

正如Swift文档-访问控制中提到的,Swift有5个访问控制:

开放和公共:可以从它们的模块实体和导入定义模块的任何模块实体中访问。 Internal:只能从其模块的实体中访问。这是默认的访问级别。 文件私有和私有:只能在您定义的有限范围内进行有限访问。


open和public的区别是什么?

open和之前版本的Swift中的public是一样的,它们允许来自其他模块的类使用和继承它们,即:它们可以从其他模块继承子类。此外,它们允许来自其他模块的成员使用和重写它们。同样的逻辑也适用于它们的模块。

Public允许来自其他模块的类使用它们,但不能继承它们,即:它们不能从其他模块子类化。此外,它们允许来自其他模块的成员使用它们,但不允许重写它们。对于它们的模块,它们具有相同的open's逻辑(它们允许类使用和继承它们;它们允许成员使用和重写它们)。

文件私有和私有的区别是什么?

私有文件可以从他们的整个文件访问。

Private只能从它们的单个声明和同一文件中该声明的扩展进行访问;例如:

// 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的访问控制有什么不同?

正如在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声明为文件私有以在整个文件中可访问。

据我所知,没有关键词“公共”,“私人”或“受保护”。这意味着一切都是公开的。

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

无论如何,这通常是一个很好的设计模式;因为它允许您更改实现类层次结构,同时保持逻辑类型系统不变。

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

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