Swift 共享实例访问继承
假设一个框架通过一个开放的Swift 共享实例访问继承,swift,inheritance,Swift,Inheritance,假设一个框架通过一个开放的类a提供可定制的服务,该类公开了一个共享实例以供使用,如下所示: open class A { public static let shared = A() open func aService() {} } A.shared.aService() override class B: A { public override func aService() { super.aService() } } class
类a
提供可定制的服务,该类公开了一个共享实例以供使用,如下所示:
open class A {
public static let shared = A()
open func aService() {}
}
A.shared.aService()
override class B: A {
public override func aService() {
super.aService()
}
}
class A {
public static var shared = A()
}
A.shared = B()
B.shared.aService() // OK! This actually calls B.aService()
该服务的常规使用情况如下:
open class A {
public static let shared = A()
open func aService() {}
}
A.shared.aService()
override class B: A {
public override func aService() {
super.aService()
}
}
class A {
public static var shared = A()
}
A.shared = B()
B.shared.aService() // OK! This actually calls B.aService()
重要注意事项:共享实例本身也在A类
代码或框架中的相关代码中使用
假设您希望通过继承来定制服务,但仍然希望按如下方式保持对共享实例的使用:
open class A {
public static let shared = A()
open func aService() {}
}
A.shared.aService()
override class B: A {
public override func aService() {
super.aService()
}
}
class A {
public static var shared = A()
}
A.shared = B()
B.shared.aService() // OK! This actually calls B.aService()
不幸的是,当您引用共享实例时,它引用的是类A
实例,您希望它引用的是继承的类实例
B.shared.aService() // Failed!: This actually calls A.shared.aService()
解决此问题的一种方法是按如下方式进行构造:
open class A {
public static let shared = A()
open func aService() {}
}
A.shared.aService()
override class B: A {
public override func aService() {
super.aService()
}
}
class A {
public static var shared = A()
}
A.shared = B()
B.shared.aService() // OK! This actually calls B.aService()
然后,在使用应用程序中的任何服务之前,请确保按以下方式更改实例:
open class A {
public static let shared = A()
open func aService() {}
}
A.shared.aService()
override class B: A {
public override func aService() {
super.aService()
}
}
class A {
public static var shared = A()
}
A.shared = B()
B.shared.aService() // OK! This actually calls B.aService()
虽然整个过程都是有效的,但我希望它是自动的,而不是依赖于更改共享实例的初始行
B.shared.aService() // Failed!: This actually calls A.shared.aService()
你会怎么做
[操场代码]说明要实现的目标,并帮助您更好地理解问题
open class A {
public static var shared = A()
open func aService() {
print("\(type(of: self)): service (from A)")
}
}
class B: A {
public override func aService() {
super.aService()
print("\(type(of: self)): service (from B)")
}
}
A.shared = B() // Question : How to remove the need to this line, yet achieving the same functionality (and output)
A.shared.aService()
B.shared.aService()
// The output (which is correct) :
//B: service (from A)
//B: service (from B)
//B: service (from A)
//B: service (from B)
有一个解决办法,但是 我个人同意这里的其他评论。这听起来真的不像是针对单身模式的工作 在当前的解决方案中,您似乎非常乐意在执行期间覆盖singleton实例,这意味着它不是singleton。假设一个单例只有一个实例,如果您可以连续创建一个新实例并将其分配给
shared
变量,而不破坏任何内容,那么您的应用程序中就不必有这种全局状态
但是,对于记录,您可以使用构成每个类的静态实例的struct
实现所需的功能,该结构可以检测调用上下文,并在每次访问shared
时返回相应的上下文:
protocol ExampleProtocol {
static var shared: ExampleProtocol { get }
func service()
}
struct ExampleProvider {
private static var a = A()
private static var b = B()
static func instance(type: ExampleProtocol.Type) -> ExampleProtocol {
return type == A.self ? ExampleProvider.a : ExampleProvider.b
}
}
class A: ExampleProtocol {
static var shared: ExampleProtocol {
return ExampleProvider.instance(type: Self.self)
}
func service() {
print("Hello")
}
}
class B: A {
override func service() {
print("Goodbye")
}
}
A.shared.service() // Hello
B.shared.service() // Goodbye
所以,是的,你可以实现你想要的。但是有一个非常有力的理由说你不应该…。这不是答案,但a类应该被宣布为最终等级,所以它不能被扩展。我希望A可以通过继承进行扩展1)如果可能,不要对扩展点使用继承。如果您只需要在某些事情发生时得到通知,请使用Observable。如果希望能够完全更改方法的实现,请使用委托模式。2) 可以有一个是final类和一个singleton,其中包含
InnerA
A
将所有操作委托给InnerA
,InnerA本身是子类化的。当创建子类时,您可以用新的InnerB
替换a
中的备份实例,但仍然只有一个a
实例,因此这对世界其他地方来说是透明的,听起来像是一个依赖注入的工作。不是单身,同意;你在这里描述的不是继承。只是全局变量碰巧是通过静态命名的。这不是提供自定义点的适当方式。Swift提供了许多更好的解决方案(如上所述)。委托或传递闭包。“类似继承”的解决方案将是脆弱的,因为它不是继承。这并没有回答问题:在您的示例中,两者都应该返回再见。另外,与我的问题相比,这是大量的代码。在我的示例中,这两个代码都不会返回“再见”。运行它。你的问题没有答案。由于其本质,您无法覆盖静态的内容。这就像问为什么我的车不能飞,即使我已经安装了机翼。。。你想做一些完全荒谬的事。在我的示例中可能有更多的代码,但是使用接口将客户机与单例类分离,这大大超过了您对大量依赖项的偏好。