传统上,在“模板方法”模式中,基类实现一些算法并遵循特定行为的派生类.这在C/C++#/
Java等语言中运行良好,因为您可以在这些方法上使用“protected”来将它们隐藏在调用者中,但使其对派生类可见.例如,在GoF书中,你有类似的东西:
class Application
{
void CreateDocument() { ..., this->DoCreateDocument() }
protected void DoCreateDocument() { } // override for custom behavior
}
这样可以保持Application的公共接口干净.在Swift中,因为你不能使用protected,所以公共接口不干净.我不希望Application的用户看到DoCreateDocument.
所以我正在尝试另一种方法,而不是使用DoCreateDocument的方法,我试图定义一个闭包并使用“仿函数”模式.
class Application
{
typealias ActionFunc = () -> ()
private let doCreateDocument : ActionFunc
init(a : ActionFunc) { self.doCreateDocument = a }
func CreateDocument() {
self.doCreateDocument()
}
}
所以这个类看起来很好 – 公共接口很干净.但是,实际使用它是不可能的.
显而易见的方法是使用派生类:
class DoApplication : Application
{
init() {
super.init(
a : {
// This would work, but you cannot use self here!
self. // anything with self. is an error
})
}
}
这种方法的问题在于,在初始化程序中,您无法将闭包传递给使用self的super.init.我在super.init之前得到了自己使用的错误.
这基本上使它无用,因为你无法访问任何状态变量.
但是,如果不在init中初始化doCreateDocument,则需要公开某些类型的setter – 同样,缺少protected也意味着setter在公共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");
}
}