在swift中通过协议使用类时,保持变量和方法的私有性



今天我遇到了一个问题,如果将类实例用作协议实例,那么保持类字段/变量和方法私有的意义何在。例如,

protocol SomeProtocol {
func someProtocolMethod()
} 
class SomeClass: SomeProtocol {
private var someVariable = ""
func someProtocolMethod() { }
}
class SuperClass {
var someInstance: SomeProtocol?
func superMethod() {
someInstance.someProtocolMethod()
}
}
let superInstance = SuperClass()
let someInstance = SomeClass()
superInstance.someInstance = someInstance

SomeClass中,我们有一个称为someVariable的私有变量。通常,为了SOLID封装类型的东西,我会直观地将其写为一个私有变量。当我今天写测试时,我遇到了一个问题,它不是已经封装好了吗?只指向协议是安全的吗?如果我不使用直接类实例并保持变量和方法的公共性,它有什么缺点吗?

外界对someInstance的唯一了解是它符合协议SomeProtocol。因此,如果someInstance是公共的,那么外部世界访问someVariable似乎没有风险。

然而,这不足以证明公开变量是合理的。我可以看到至少3个不这样做的原因:

  • SomeClass可以单独使用,而不仅仅是通过它所遵守的协议。毕竟,重用是OO设计中的驱动因素之一。在这种情况下,公开一些本应保密的事情可能会在以后被证明是短视的
  • 初始化someInstance的上下文非常清楚对象的真实类型,并且可能会滥用不打算直接更改的公共属性。这里的风险在你的例子的最后3行
  • 最后,可以对真实类型进行一些下转换,然后暴露应该是私有的公共成员:
    class SuperClass {
    var someInstance: SomeProtocol?   // optional or initializer
    func superMethod() {
    someInstance?.someProtocolMethod()
    if let oops = someInstance as? SomeClass {  // Downcast
    oops.someVariable = "hacked!"           // successful
    print (oops.someVariable)
    }
    else {
    print ("No access")                     // downcast failed
    }
    }
    }
    

结论:始终保持隐私,不必公开。当然,如果所有这些类的使用都是有限的,即仅用于测试目的,并且您是唯一的维护者,那么误用的风险可能很低。但为什么要养成坏习惯;想想你的遗产;-)

关于性能,这里公共访问和私有访问之间没有区别。访问是在编译/汇编时管理的。这里的性能受到协议的轻微影响,该协议意味着动态调度。但是,除非你在视频游戏的主循环中编写一个操作系统或函数,否则它太小了,根本不相关。