假设场景:
有类:ClassA
;和 ClassB
。两者都实现了 ProtocolC
,其中包含单一要求 func createKey()
。 ProtocolC
有一个 extension
实现了 createKey()
因为关于这个函数,ClassA
和ClassB
是相同的。但是,createKey()
的实现需要访问 ClassA
和 ClassB
都包含的名为 uniqueKey
的私有(private)变量,其值在两个类中需要不同(如您所想)。 ProtocolC
中 createKey()
的 extension
因此变得无用 - 因为变量是 fileprivate
- 这意味着它的代码有在 ClassA
和 ClassB
中复制。但重复代码是编程禁忌。一个解决方案可能是使用父类(super class)而不是协议(protocol)扩展,但这与 Swift 试图实现的目标背道而驰。继承是 Swift 的禁忌。
// the ideal:
class ClassA: ProtocolC {
fileprivate var uniqueKey: String?
}
class ClassB: ProtocolC {
fileprivate var uniqueKey: String?
}
protocol ProtocolC {
func createKey()
}
extension ProtocolC {
func createKey(){
uniqueKey = NSUUID().uuidString
}
}
// the reality:
class ClassA: ProtocolC {
fileprivate var uniqueKey: String?
func createKey(){
uniqueKey = NSUUID().uuidString
}
}
class ClassB: ProtocolC {
fileprivate var uniqueKey: String?
func createKey(){
uniqueKey = NSUUID().uuidString
}
}
uniqueKey
需要锁定在两个类中,不可设置也不可从外部获取。 Swift 中写什么解决方案:可以访问私有(private)属性的泛型代码;同时避免继承?
感谢阅读。
最佳答案
这里有一些非常接近您的理想。缺点是在扩展方法中转换了运行时协议(protocol),但它实现了您正在寻找的访问控制级别(fileprivate
存储的 var)和通过协议(protocol)扩展的代码重用:
fileprivate protocol UniqueKeyDefining {
var uniqueKey: String? { get set }
}
class ClassA: ProtocolC, UniqueKeyDefining {
fileprivate var uniqueKey: String?
}
class ClassB: ProtocolC, UniqueKeyDefining {
fileprivate var uniqueKey: String?
}
protocol ProtocolC {
func createKey()
}
extension ProtocolC {
func createKey(){
if var hasUniqueKey = self as? UniqueKeyDefining {
hasUniqueKey.uniqueKey = NSUUID().uuidString
} else {
// Some default behavior if the conformer to ProtocolC isn't also UniqueKeyDefining
}
}
}
协议(protocol) UniqueKeyDefining
在声明它的文件之外是不可见的,具有 ClassA
和 ClassB
,所以没有代码在文件知道那些类符合它或者可以看到它们的 uniqueKey
ivars。
ProtocolC
的特定协议(protocol)扩展在同一文件中声明,因此它确实知道UniqueKeyDefining
并且可以有条件地转换 self
在运行时访问该协议(protocol),以通过该 fileprivate 协议(protocol)访问 uniqueKey
ivar。
它似乎不是非常可扩展或可重用此文件之外的类,但它满足我从你的问题中解释的一组狭窄的要求。
关于swift - 如何使用 Swift 协议(protocol)扩展来创建可以修改私有(private)属性的共享代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47563874/