我正在尝试以惯用方式转换 Kotlin 中称为责任链的设计模式的 Java 代码。但是我对appendNext()
在 Kotlin 中转换 Java 接口的默认方法没有任何线索。我尝试了一些已经存在的问题,例如this和this,但它们似乎不适用于我的用例。
我尝试将默认方法转换为appendNext()
Kotlin 中的扩展函数。但显然 Kotlin 似乎没有找到方法Logger.message()
并 throws NoSuchMethodError
。
我在以下片段中给出了迄今为止我尝试过的原始 Java 代码和 Kotlin 代码。
我更喜欢此代码的 Kotlin 惯用解决方案,而不使用@JvmDefault
注释。代码应该和 Java 一样简洁。任何帮助将非常感激。
Java 代码
这是设计模式责任链的正确工作 Java 代码:
import java.util.Arrays;
import java.util.EnumSet;
import java.util.function.Consumer;
@FunctionalInterface
public interface Logger {
public enum LogLevel {
INFO, DEBUG, WARNING, ERROR, FUNCTIONAL_MESSAGE, FUNCTIONAL_ERROR;
public static LogLevel[] all() {
return values();
}
}
abstract void message(String msg, LogLevel severity);
default Logger appendNext(Logger nextLogger) {
return (msg, severity) -> {
message(msg, severity);
nextLogger.message(msg, severity);
};
}
static Logger writeLogger(LogLevel[] levels, Consumer<String> stringConsumer) {
EnumSet<LogLevel> set = EnumSet.copyOf(Arrays.asList(levels));
return (msg, severity) -> {
if (set.contains(severity)) {
stringConsumer.accept(msg);
}
};
}
static Logger consoleLogger(LogLevel... levels) {
return writeLogger(levels, msg -> System.err.println("Writing to console: " + msg));
}
static Logger emailLogger(LogLevel... levels) {
return writeLogger(levels, msg -> System.err.println("Sending via email: " + msg));
}
static Logger fileLogger(LogLevel... levels) {
return writeLogger(levels, msg -> System.err.println("Writing to Log File: " + msg));
}
public static void main(String[] args) {
// Build an immutable chain of responsibility
Logger logger = consoleLogger(LogLevel.all())
.appendNext(emailLogger(LogLevel.FUNCTIONAL_MESSAGE, LogLevel.FUNCTIONAL_ERROR))
.appendNext(fileLogger(LogLevel.WARNING, LogLevel.ERROR));
// Handled by consoleLogger since the console has a LogLevel of all
logger.message("Entering function ProcessOrder().", LogLevel.DEBUG);
logger.message("Order record retrieved.", LogLevel.INFO);
// Handled by consoleLogger and emailLogger since emailLogger implements Functional_Error & Functional_Message
logger.message("Unable to Process Order ORD1 Dated D1 For Customer C1.", LogLevel.FUNCTIONAL_ERROR);
logger.message("Order Dispatched.", LogLevel.FUNCTIONAL_MESSAGE);
// Handled by consoleLogger and fileLogger since fileLogger implements Warning & Error
logger.message("Customer Address details missing in Branch DataBase.", LogLevel.WARNING);
logger.message("Customer Address details missing in Organization DataBase.", LogLevel.ERROR);
}
}
科特林代码
这是我到目前为止所尝试的。我将其Enum
移至一个单独的文件并将所有内容都保留在顶层。看看appendNext()
方法,这似乎是问题的原因。
记录器.kt
import java.util.*
import java.util.function.Consumer
interface Logger {
fun message(message: String, severity: LogLevel)
}
fun Logger.appendNext(nextLogger: Logger): Logger {
return object: Logger {
override fun message(message: String, severity: LogLevel) {
message(message, severity)
nextLogger.message(message, severity)
}
}
}
fun writeLogger(
stringConsumer: Consumer<String>,
vararg levels: LogLevel
): Logger {
val set = EnumSet.copyOf(listOf(*levels))
return object: Logger {
override fun message(message: String, severity: LogLevel) {
if (set.contains(severity)) {
stringConsumer.accept(message)
}
}
}
}
fun consoleLogger(vararg levels: LogLevel): Logger {
return writeLogger(
Consumer { msg: String -> System.err.println("Writing to console: $msg") },
*levels
)
}
fun emailLogger(vararg levels: LogLevel): Logger {
return writeLogger(
Consumer { msg: String -> System.err.println("Sending via email: $msg") },
*levels
)
}
fun fileLogger(vararg levels: LogLevel): Logger {
return writeLogger(
Consumer { msg: String -> System.err.println("Writing to Log File: $msg") },
*levels
)
}
fun main() {
// Build an immutable chain of responsibility
val logger = consoleLogger(*LogLevel.all())
.appendNext(emailLogger(LogLevel.FUNCTIONAL_MESSAGE, LogLevel.FUNCTIONAL_ERROR))
.appendNext(fileLogger(LogLevel.WARNING, LogLevel.ERROR))
// Handled by consoleLogger since the console has a LogLevel of all
logger.message("Entering function ProcessOrder().", LogLevel.DEBUG)
logger.message("Order record retrieved.", LogLevel.INFO)
// Handled by consoleLogger and emailLogger since emailLogger implements Functional_Error & Functional_Message
logger.message("Unable to Process Order ORD1 Dated D1 For Customer C1.", LogLevel.FUNCTIONAL_ERROR)
logger.message("Order Dispatched.", LogLevel.FUNCTIONAL_MESSAGE)
// Handled by consoleLogger and fileLogger since fileLogger implements Warning & Error
logger.message("Customer Address details missing in Branch DataBase.", LogLevel.WARNING)
logger.message("Customer Address details missing in Organization DataBase.", LogLevel.ERROR)
}
日志级别.kt
enum class LogLevel {
INFO, DEBUG, WARNING, ERROR, FUNCTIONAL_MESSAGE, FUNCTIONAL_ERROR;
companion object {
public fun all(): Array<LogLevel> {
return values()
}
}
}