今天我遇到了一个问题,如果将类实例用作协议实例,那么保持类字段/变量和方法私有的意义何在。例如,
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 } } }
结论:始终保持隐私,不必公开。当然,如果所有这些类的使用都是有限的,即仅用于测试目的,并且您是唯一的维护者,那么误用的风险可能很低。但为什么要养成坏习惯;想想你的遗产;-)
关于性能,这里公共访问和私有访问之间没有区别。访问是在编译/汇编时管理的。这里的性能受到协议的轻微影响,该协议意味着动态调度。但是,除非你在视频游戏的主循环中编写一个操作系统或函数,否则它太小了,根本不相关。