传统上,在“模板方法”模式中,基类实现一些算法并遵循派生类的特定行为。这在 C++/C#/Java 之类的语言中效果很好,因为您可以在这些方法上使用“ protected ”以将它们对调用者隐藏,但对派生类保持可见。例如,在 GoF 书中,您有类似的内容:
class Application
{
void CreateDocument() { ..., this->DoCreateDocument() }
protected void DoCreateDocument() { } // override for custom behavior
}
这使
Application
的公共(public)接口(interface)保持干净。在 Swift 中,因为不能使用 protected
,所以公共(public)接口(interface)不干净。我不希望 Application
的用户看到 DoCreateDocument
。所以我正在尝试另一种方法,它不是使用
DoCreateDocument
的方法,而是尝试定义一个闭包并使用“仿函数”模式。class Application
{
typealias ActionFunc = () -> ()
private let doCreateDocument : ActionFunc
init(a : ActionFunc) { self.doCreateDocument = a }
func CreateDocument() {
self.doCreateDocument()
}
}
所以这个类看起来不错——公共(public)接口(interface)很干净。但是,实际使用它是不可能的。
显而易见的方法是使用派生类:
class DoApplication : Application
{
init() {
super.init(
a : {
// This would work, but you cannot use self here!
self. // anything with self. is an error
})
}
}
这种方法的问题在于,在初始化程序中,您不能将闭包传递给使用
super.init
的 self
。我收到错误 self used before super.init
。这基本上使它变得无用,因为您无法访问任何状态变量。
但是,如果您不在
doCreateDocument
中初始化 init
,则需要公开某种 setter - 同样,缺少 protected
意味着 setter 位于公共(public) API 上。哎呀。那么有没有什么方法可以干净地实现保持界面干净的模板模式呢?
最佳答案
我知道这是一个丑陋的黑客,但它有效。
class DoApplication: Application {
init() {
var doCreateDocument: (Application.ActionFunc)!
super.init(a: { doCreateDocument() })
doCreateDocument = { [unowned self] in
self.foo()
}
}
func foo() {
println("DoApplication.foo");
}
}
或者,您可以将
self
传递给 doCreateDocument
:class Application {
typealias ActionFunc = (Application) -> ()
private let doCreateDocument : ActionFunc
init(a : ActionFunc) { self.doCreateDocument = a }
func CreateDocument() {
self.doCreateDocument(self)
}
}
class DoApplication : Application {
init() {
super.init(a : { _self in
let _self = _self as! DoApplication
_self.foo()
})
}
func foo() {
println("DoApplication.foo");
}
}
关于Swift:如何支持 "template method"设计模式(因为 Swift 没有保护)?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31757514/