如何在 swift 中声明一个 'protected' 变量

How to declare a 'protected' variable in swift

我想创建一个继承自另一个 class 的 class,它位于不同的文件中。

例如:

Class1.swift

class Class1
{
    protected var 
    //Do Stuff
}

Class2.swift

class Class2:Class1
{
    //Do stuff
}

我怎样才能访问 swift 中的 'protected' variable/function?

当我声明一个私有 variable/function 时,我只能在那个 class 中使用它。如果我使用 'fileprivate',我的另一个 class 必须与 Class1 在同一个文件中。我想做的是将我的 classes 保存在单独的文件中,并使用 Xcode 中的组来了解 class 属于哪个类别。

您必须为此使用 internal,因为 Swift 不提供 protected 关键字(与许多其他编程语言不同)。 internalfileprivatepublic 之间唯一的访问修饰符:

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.

有一个 blog post 可以更多地解释为什么语言设计者选择不提供 protected 关键字(或任何等效的关键字)。

部分原因是

It doesn’t actually offer any real protection, since a subclass can always expose “protected” API through a new public method or property.

还有 protected 会在扩展​​方面引起问题的事实,因为不清楚扩展是否也应该访问 protected 属性。

即使 Swift 不提供 protected 访问权限,我们仍然 可以通过使用 fileprivate 访问控制实现类似的访问权限
我们唯一需要记住的是,我们需要将所有子项声明在与父项声明相同的文件中。

Animal.swift

import Foundation

class Animal {
    fileprivate var protectedVar: Int = 0
}

class Dog: Animal {
    func doSomething() {
        protectedVar = 1
    }
}

OtherFile.swift

let dog = Dog()
dog.doSomething()

对此类受保护的变量使用下划线:/

就是这样......

class RawDisplayThing {
    
    var _fraction: CGFloat = 0 {
        didSet { ... }
    }


class FlightMap: RawDisplayThing() {

    var currentPosition() {
        ...
        _fraction = 
        ...
    }
}

大家不得不“同意”只有概念class才能使用“_”变量和函数

至少,全局搜索每个“_”项目并确保它只被超级classes使用是相对容易的。

或者,在这些概念前面加上“本地”、“显示”或 class 的名称(或任何对您的团队有意义的名称)。

class RawDisplayThing {
    
    var rawDisplayFraction: ...
    var rawDisplayTrigger: ...
    var rawDisplayConvolution: ...

等等等等。也许有帮助:/

在我看来,下一个最好的做法是将 类 放在同一个文件中,然后使用 fileprivate

class Class1 {
   fileprivate var foo: String
}

final class Class2: Class1 {
   func bar() {
      // Class1.foo is accessible from Class1 but nothing else
      self.foo = "bar" 
   }
}

如果您不想让两个 class 都属于同一个文件,您可以这样做:

class Parent {
    internal private(set) var myProtectedBoolean = false
}

然后在 child class:

class Child: Parent {
   private var _myProtectedBoolean: Bool = false;

   override var myProtectedBoolean: Bool {
       get { return _myProtectedBoolean }
       set { _myProtectedBoolean = newValue }
   }
}