如何在Kotlin中实现模板方法设计模式?
考虑这个问题:
我们有一个抽象方法的Base
类。 现在,我们想强制执行这个方法的每一个重写将执行一些参数检查或一些其他的苦差事。 我们希望这个参数检查在所有覆盖中都是相同的。 一种解决方案是将这种行为包装在一个非抽象方法中,该方法调用抽象方法:
abstract class Base { fun computeSomething(argument: Int): Int { require(argument > 0) // Some intricate checking return execute(argument) } // Pure functionality, assuming correct arguments // Ideally, this would be private. protected abstract fun execute(validArgument: Int): Int } class Derived1: Base() { override fun execute(validArgument: Int): Int = validArgument * validArgument } class Derived2: Base() { override fun execute(validArgument: Int): Int = validArgument * validArgument * validArgument } fun main(args: Array<String>) { val d = Derived1() println(d.computeSomething(23)) }
我想有Base::execute
private,这样Base
任何子类都可以不经意地调用它而不检查它的参数。 不幸的是,这是不可能的:
错误:(9,5)Kotlin:修饰符'private'与'abstract'不兼容
Kotlin的protected
优于Java的protected
,因为它使得该功能只能访问子类,但是仍然是理想的情况。
那么是否有一些正确的方法来实现这种模式? 而且,出于好奇, private
的不兼容性和abstract
的语言设计的故意选择?
一个函数被覆盖是没有意义的,但是不能从这个类中调用。 通过重写这个函数,你拥有它的实现,因此可以调用它。
你可以通过从派生类中分离执行逻辑来完成你想要的任务,这可以通过几种方式完成:
- 你可以使用lambda,并将其传递给
Base
的构造函数 - 你可以创建一个处理执行逻辑的接口实现
通过将这些传递给构造函数中的Base
类,您将把它们的所有权转移给该类。
你可以让它们传递将检查值的对象,如果他们想调用这个方法。 例
abstract class Base { fun computeSomething(argument: Int): Int { return execute(ValueCheck(argument)) } protected abstract fun execute(validArgument: ValueCheck) protected class ValueCheck(a: Int) { private val value = checkValue(a) private fun checkValue(argument: Int): Int { require(argument > 0) return argument } fun get() = value } }
而当派生类想调用execute时,必须在创建实例时传递正在检查值的对象