我需要在一致的类中使用协议属性作为私有。但是编译器拒绝这样做。我该如何实现呢?
protocol ProtocolX: class {
var x: Int { get set }
func performAnyActionOnX()
}
extension ProtocolX {
func performAnyActionOnX() {
x = 5
print(x)
}
}
class A: ProtocolX {
private var x:Int = 7
}
感谢。
答案 0 :(得分:0)
由于协议的属性始终与您的协议具有相同的访问级别,因此您可以创建一个单独的类,您可以在其中对它们应用 fileprivate
级别,例如:
public class Props {
fileprivate var x: Int = 0
}
public protocol ProtocolX: class {
var privateProps: Props { get }
}
extension ProtocolX {
public func performAnyActionOnX() {
privateProps.x = 5
print(privateProps.x)
}
}
public class A: ProtocolX {
public let privateProps = Props()
public init() {
privateProps.x = 7
}
}
如您所见,x
具有 fileprivate
访问级别,因此只能在 ProtocolX 扩展和 A 类实现中访问它,因此它的行为与 private
相同,您无法更改 {{ 1}} 类变量 privateProps
和对外部 A
的访问:
x
答案 1 :(得分:-1)
根据@ TheAppMentor评论中所述的原因,您的问题没有确切的解决方案。但是,如果您的目的是使您的代码可以理解为人类(而不是欺骗编译器),那么可能会有一些解决方法。
在Swift 4.0中编译。
快速而简单。此解决方案依赖于同意从_
开始的属性和函数是私有且不应被访问的用户。
protocol ProtocolX: class {
// Public x
var x: Int { get }
// It's private!
var _x: Int { get set }
func performAnyActionOnX()
}
extension ProtocolX {
var x: Int { return _x }
func performAnyActionOnX(){
_x = 5
print(x)
}
}
class A: ProtocolX {
var _x: Int = 7
}
架构正确。您应该将协议分为两部分:私有和公共。
protocol ProtocolX: class {
var x: Int { get }
func performAnyActionOnX()
}
protocol ProtocolXImplementation: class {
var _x: Int { get set }
}
extension ProtocolXImplementation {
var x: Int { return _x }
func performAnyActionOnX(){
_x = 5
print(x)
}
}
class A: ProtocolX, ProtocolXImplementation {
var _x: Int = 7
}
// ... somewhere later ...
// Hide the implementation when use `A`:
let item: ProtocolX = A()
答案 2 :(得分:-1)
正如@TheAppMentor所提到的,从Swift 4开始,似乎没有确切的解决方案。
但是,有两种近似的解决方案:
1。)
由于默认情况下,Swift中的协议的访问级别为internal
,因此将变量也设为internal
。为了使internal
由编译器强制执行,请将协议,类及其所有使用者(用户)移动到单独的模块(框架)。
/* internal */ protocol ProtocolX: class {
var x: Any { get set }
func performAnyActionOnX()
}
extension ProtocolX {
func performAnyActionOnX() {}
}
/* internal */ class A: ProtocolX {
internal var x: Any = 0
}
2。)
为协议提供private
的访问级别,为变量提供fileprivate
的访问级别。为了使private
协议可访问,请将协议,类及其所有使用方移动到同一源文件中。
private protocol ProtocolX: class {
var x: Any { get set }
func performAnyActionOnX()
}
extension ProtocolX {
func performAnyActionOnX() {}
}
class A: ProtocolX {
fileprivate var x: Any = 0
}