如何在 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
关键字(与许多其他编程语言不同)。 internal
是 fileprivate
和 public
之间的唯一访问修饰符:
内部访问使实体可以在任何源文件中使用 来自他们的定义模块,但不在此之外的任何源文件中 模块。在定义应用程序或 框架的内部结构。
有一个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 中声明一个“受保护”变量的主要内容,如果未能解决你的问题,请参考以下文章
如何在子类中访问超类的“受保护的静态”变量,子类位于不同的包中......?