我已经看过在Scala中登录的示例,它通常看起来像这样:
import org.slf4j.LoggerFactory
trait Loggable {
private lazy val logger = LoggerFactory.getLogger(getClass)
protected def debug(msg: => AnyRef, t: => Throwable = null): Unit =
{...}
}
这似乎与具体的日志记录框架无关。虽然这样做了,但它还在每个想要进行日志记录的实例中引入了一个无关的延迟val ,这可能是整个应用程序的每个实例。这对我来说似乎太沉重了,特别是如果你有许多特定类型的“小实例”。
有没有办法将记录器放在具体类的对象中,只需使用继承?如果我必须在类的对象中显式声明记录器,并从类/特性中显式地引用它,那么我编写的代码几乎和我根本没有重用的代码一样多。
在非日志记录特定上下文中表示,问题是:
如何在特征中声明实现类必须具有X类型的单例对象,并且必须通过方法def x:X来访问此单例对象?
我不能简单地定义一个抽象方法,因为类中只能有一个实现。我希望在超级类中登录让我获得超类单例,并且登录子类会让我获得子类单例。或者更简单地说,我希望登录Scala能像Java中的传统日志一样工作,使用特定于执行日志记录的类的静态记录器。我目前对Scala的了解告诉我,如果不像Java那样完全相同,这是不可能的,使用“更好”的Scala没有太多好处。
答案 0 :(得分:12)
首先要明确一件事:如果你的特质看起来像这样:
trait Logger { lazy val log = Logger.getLogger }
然后不完成的内容如下:
请注意,即使您确实为每个类型的实例创建了一个单独的记录器(我经常这样做,即使我的程序包含数十万个这样的记录器,所以我也很好 - 对我的日志记录的控制,你几乎可以肯定既没有性能也没有内存问题!
一个“解决方案”是(当然),以使伴侣对象实现记录器接口:
object MyType extends Logger
class MyType {
import MyType._
log.info("Yay")
}
答案 1 :(得分:6)
如何在特征中声明 实施班必须有一个 X类型的单例对象,以及 这个单例对象必须是 可通过方法def x:X?
访问
声明必须由伴侣对象实现的特征。
trait Meta[Base] {
val logger = LoggerFactory.getLogger(getClass)
}
为您的类创建基本特征,子类必须覆盖元方法。
trait Base {
def meta: Meta[Base]
def logger = meta.logger
}
一个类与伴侣对象无关:
object Whatever extends Meta[Base]
class Whatever extends Base {
def meta = Whatever
def doSomething = {
logger.log("oops")
}
}
通过这种方式,您只需要引用元对象。
我们可以使用这样的Whatever类。
object Sample {
def main(args: Array[String]) {
val whatever = new Whatever
whatever.doSomething
}
}
答案 2 :(得分:0)
我不确定我完全理解你的问题。如果这不是您正在寻找的答案,我会在前面道歉。
如果您将object
放入logger
,则定义trait
,然后创建一个伴随object Loggable {
private val logger = "I'm a logger"
}
trait Loggable {
import Loggable._
def debug(msg: String) {
println(logger + ": " + msg)
}
}
。
scala> abstract class Abstraction
scala> class Implementation extends Abstraction with Loggable
scala> val test = new Implementation
scala> test.debug("error message")
I'm a logger: error message
所以现在你可以像这样使用它:
{{1}}
这会回答你的问题吗?
答案 3 :(得分:0)
我认为您无法自动获取类的相应单例对象或要求存在这样的单例。
一个原因是在定义单例之前你无法知道它的类型。不确定,如果这有帮助或者它是您问题的最佳解决方案,但如果您想要使用特定特征定义某个元对象,您可以定义类似的内容:
trait HasSingleton[Traits] {
def meta: Traits
}
trait Log {
def classname: String
def log { println(classname) }
}
trait Debug {
def debug { print("Debug") }
}
class A extends HasSingleton[Log] {
def meta = A // Needs to be defined with a Singleton (or any object which inherits from Log}
def f {
meta.log
}
}
object A extends Log {
def classname = "A"
}
class B extends HasSingleton[Log with Debug] { // we want to use Log and Debug here
def meta = B
def g {
meta.log
meta.debug
}
}
object B extends Log with Debug {
def classname = "B"
}
(new A).f
// A
(new B).g
// B
// Debug