logger使ってますか?
Log4jとかlog4j2とかslf4jとか 色々なloggerがあると思います。
javaだったらlombockのアノテーションでいい感じにloggerを注入してくれて便利ですが、kotlinでlombockを使っても、イマイチ捗りません。
だからといって下記のようにjavaのコードを素直にkotlinに書き換える感じもめんどくさいです。特に自分で生成したクラスをいちいちLoggerに渡さないといけないなんて面倒極まりない。
ということでkotlinならどう書いたら面倒が少ないのか考えてみました。
なお利用しているloggerはlog4j2ということにしてあります。但し、ちょっと書き換えれば他のloggerでも利用可能です。
class LogExample{
private static final Logger log = LogManager.getLogger(LogExample.class);
}
class LogExample(){
companion object{
private val log = LogManager.getLogger(LogExample::class.java)
}
}
##1.companion objectに継承
以下のうようにKtLogというクラスを作ります。(クラス名はなんでもいいです。)
open class KtLog(){
var log:Logger = LogManager.getLogger(
this.javaClass.name.let {
val matchIndex = it.length - 10
when (it.lastIndexOf("\$Companion")) {
matchIndex -> it.substring(0, matchIndex)
else -> it
}
}
)
}
使うときはcompanion object:KtLog()
のようにcompanion objectに継承します。
class LogExample(){
companion object:KtLog()
fun nanika(){
log.debug("なにか")
}
}
デメリットとしてはcompanion objectに他のクラスを継承させることが不可能なことです。
またKtLogではthis.javaClass
がLogExample$Companion
となる為、クラス名を戻す処理をしています。
##2.byを使う
こちらもKtLogの様なクラスを作成します。(クラス名はなんでもいいです。)
class KtLog {
var log:Logger? = null
operator fun getValue(thisRef:Any,property: KProperty<*>):Logger{
return log?:LogManager.getLogger(thisRef.javaClass.name.let {
val matchIndex = it.length - 10
when (it.lastIndexOf("\$Companion")) {
matchIndex -> it.substring(0, matchIndex)
else -> it
}
}).apply { this@KtLog.log = this }
}
}
使うときはcompanion object
内でprivate val log by KtLog()
を記述するだけです。
class LogExample(){
companion object{
private val log by KtLog()
}
fun nanika(){
log.debug("なにか")
}
}
なお、companion object
内に記述しなくてもOKですが、生成したオブジェクト毎にloggerが生成されてしまいます。パフォーマンスを気にしないのであればこれでも構いません。
class LogExample(){
private val log by KtLog()
fun nanika(){
log.debug("なにか")
}
}
メリットとしては1の方法と違いcompanion objectは継承可能である点と、logの変数を自由に変更できる点です。
##結論
おそらく2のほうが使い勝手はいいと思います。
ただ欲を言えばアノテーションを書くだけで注入してほしい・・・。