如何在 swift 中声明一个“受保护”变量

Posted

技术标签:

【中文标题】如何在 swift 中声明一个“受保护”变量【英文标题】:How to declare a 'protected' variable in swift 【发布时间】:2017-06-05 12:29:51 【问题描述】:

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

例如:

Class1.swift

class Class1

    protected var 
    //Do Stuff

Class2.swift

class Class2:Class1

    //Do stuff

我如何能够在 swift 中访问“受保护”变量/函数?

当我声明一个私有变量/函数时,我只能在那个类中使用它。如果我使用'fileprivate',我的其他类必须与Class1 在同一个文件中。我想要做的是将我的类保存在单独的文件中,并使用 Xcode 中的 Groups 来了解哪个类属于哪个类别。

【问题讨论】:

Does Swift have access modifiers?的可能重复 @Sulthan 我看到了那个帖子,因为它没有说任何关于“受保护”的内容。这可能是后来版本的 swift 中添加的东西,或者以不同的方式访问。 Xcode 中的组与编译或语言本身无关。这只是对项目中的文件进行逻辑分组的一种方式,与文件系统中的文件夹相同。如果要单独实现,就必须使用modules,即项目中的targets。然后使用internal 我链接的帖子已针对 Swift 3 进行了更新。 @我知道这些组。我喜欢在不同的文件中有类,所以我很容易看到每个类等在文件结构中的位置。 【参考方案1】:

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

内部访问使实体可以在任何源文件中使用 来自他们的定义模块,但不在此之外的任何源文件中 模块。在定义应用程序或 框架的内部结构。

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

其中一些原因

它实际上并没有提供任何真正的保护,因为子类可以 始终通过新的公共方法或属性公开“受保护”的 API。

还有protected 会在涉及扩展时引起问题的事实,因为不清楚扩展是否也应该可以访问protected 属性。

【讨论】:

感谢您的回答。我知道有内部代码,但是由于所有代码都在一个单元中,这意味着我不妨将其公开。 @iProgram 但这就是问题所在。您将所有代码集中在一个单元中。 想一想这就是应用程序的发展方向。那么在制作应用程序时,所有东西都应该在不同的单元中吗?如果是这样,这样做的最佳方法是什么?或者是为了另一个主题?虽然我对开发并不陌生,但如果你明白我的意思,我就是。 有几种设计模式,但最常见的是Model-View-Controller【参考方案2】:

即使 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()

【讨论】:

问题是超类和子类必须在同一个文件中。这将是一个代码设计问题。 没有更好的答案,尽管“继承”是设计者决定不使用的“轴”。唯一实用的解决方案是对实例变量使用文件分离,并智能地使用文件来分离访问控制中省略的“轴”,即 D4ttatraya 提出的。【参考方案3】:

对这些受保护的变量使用下划线:/

就是这样……

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


class FlightMap: RawDisplayThing() 

    var currentPosition() 
        ...
        _fraction = 
        ...
    

每个人都必须“同意”只有概念类才能使用“_”变量和函数。

至少,在每个“_”项上全局搜索并确保它仅由超类使用是相对容易的。

或者,在这些概念前面加上“local”、“display”或类名(或任何对您的团队有意义的名称)。

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

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

【讨论】:

不明白为什么这种语言还没有提供这么基本的功能。来自 Java/android,我必须花费数小时寻找 DIY 变通方法,以在我自己的基本 C++ 上制作,例如受保护或抽象类等功能,而许多其他语言刚刚设置了它们(php、C#、Java、Kotlin , ..) (FTR 这篇好文章 medium.com/ios-os-x-development/… 确实链接到 Swift Guys's Writing 中他们证明这个问题的确切位置。对我来说,这一切都很糟糕,给我汇编程序 :))跨度> 大声笑,我实际上发现 Java 非常擅长在编译时强制执行规则,这来自于 UML 业务模型。很多语言都只有这些类似 C++ 的特性。事实上 Swift 并没有强迫我花时间重新审视我的 UML 业务逻辑,这非常令人沮丧...... 要获得完整的好苹果/坏苹果体验,不妨试试 CoreData!哦,我的..【参考方案4】:

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

class Parent 
    internal private(set) var myProtectedBoolean = false

然后在子类上:

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

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

【讨论】:

【参考方案5】:

在我看来,下一个最好的办法是将两个类放在同一个文件中,并改用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" 
   

【讨论】:

以上是关于如何在 swift 中声明一个“受保护”变量的主要内容,如果未能解决你的问题,请参考以下文章

如何在 javascript 类中模拟受保护的变量?

如何在子类中访问超类的“受保护的静态”变量,子类位于不同的包中......?

基类有没有办法在不污染 .h 文件的情况下声明受保护的变量?

如何影响派生类中受保护的基变量

如何在js中轻松制作受保护的变量?

如何在同一个类的静态方法中访问类的受保护变量?