I'm currently constructing loggers (with configgy) like this:
class MyClass {
private val log = Logger.get(classOf[MyClass])
}
I would like to avoid repeating "MyClass" as in classOf[MyClass] (for example I want to quickly copy paste the log definition line, without smart IDE expanding the template with the class name), but I don't want to use the dynamic class of the current object, like:
class MyClass {
private val log = Logger.get(this.getClass)
}
EDIT: because this way instances of subclasses will have the subclass class object passed to the parent logger:
class MyClass {
private val log = Logger.get(this.getClass)
def doit = log.info("doing")
}
class SubClass extends MyClass {
}
new SubClass().doit
will use the logger configured for SubClass, not MyClass as I want.
Is there a way to have some fixed expression which somehow yields the class which is being defined at that point?
The short answer is that Scala doesn't have a way to do that. The long answer is that you can do it, but it's an ugly hack. The hack is to use the fact that exception stack traces include the name of the static class definition where the stack trace was created. Parse and tada. But, seriously, don't do this. Or, if you do, move it to a mixin trait and modify the parsing bit to pull the class name from the appropriate spot in the trace. Also, I've only tested this in some fairly limited conditions: no guarantee that it will work everywhere.
class MyClass {
private val log = Logger get (Class forName (
new RuntimeException().getStackTrace.apply(0).toString takeWhile
(_ != '(') split "\\." dropRight 1 mkString "."))
def doit = log.info("doing")
}
Surely you can just use the protected access modifier and access it directly?
class MyClass {
protected val log = Logger.get(classOf[MyClass])
}
class SubClass extends MyClass {
}
new SubClass().doit
Related
I am trying to add behavior to the setters of a variable within a class. To keep things simple let's say that I want to print something to the console whenever a variable is set. Moreover, I want to achieve this using reflection from within a trait that is mixed in the class.
Consider the following code:
class Foo(var bar: String) extends Logger {}
trait Logger { self =>
// create mirrors to reflect on the delegate
private val runtimeMr = runtimeMirror(self.getClass.getClassLoader)
private val instanceMr = runtimeMr.reflect(self)
}
How can I now:
1) get the setter method(s) from the instanceMr and, more importantly
2) add behavior to the execution of the setter (in my case printing bar before setting it)
This question is somewhat hard to summarize. Following code block shows what I want to do.
I have a base class like this:
`class Base {
def methA:String="ook"
def methB:Int=1
}
Also I have a derived class, where I want each subclass method to call the super class method twice, compare the results and throw an exception on mismatch (this is for a test scenario).
But if I write
class Derived extends Base {
private def callDoublyAndCompare[T](fun:()=>T) : T = {
val fst=fun()
val snd=fun()
if(fst!=snd) throw new RuntimeException(s"Mismatch fst=$fst != snd=$snd")
snd
}
override def methB:Int={
callDoublyAndCompare(() => super[Derived].methB)
}
}
Then this will not compile. The only way out of this problem sofar has been to extract a method in class Derived which only calls the superclass' methB and to call this from the lambda call.
Is there a better way?
I understood you want to call super call method. Hope below is what you want.
You can call that as below with the key word super only
(new Derived).methB . This will call super call method in callDoublyAndCompare twice as per your code .
class Derived extends Base {
private def callDoublyAndCompare[T](fun:()=>T) : T = {
val fst=fun()
val snd=fun()
if(fst!=snd) throw new RuntimeException(s"Mismatch fst=$fst != snd=$snd")
snd
}
override def methB:Int={
callDoublyAndCompare(() => super.methB) //kept only super
}
}
The original example was not fully complete insofar as the Derived class was defined as inner class of another scala class.
After I moved out this inner class to the top level, the example from Praveen above suddenly worked.
In Java I would write logger.getLogger(NameOfClass.class). How to write the same in Scala?
You could try:
logger.getLogger(getClass())
or:
logger.getLogger(classOf[NameOfClass])
As a side note, ScalaLogging provides a nice and easy way to use a logger with the class name but without all of the boilerplate like normal java. You get a logger in your class setup properly and all you have to do is extend a trait Logging:
class MyClass extends Logging {
logger.debug("This is very convenient ;-)")
}
Don't forget to define the logger on the singleton companion object:
object MyClass {
// Commons logging
private val clLogger = LogFactory.getLog(getClass())
// java.util.logging
private val juLogger = Logger.getLogger(getClass().toString)
}
class MyClass {
import MyClass._
...
}
The reason one should do this is that if you place the field on the class it's an instance field which goes back to the logger factory on every new instance of an object of that class. This can be unnecessary/unacceptable performance for some classes.
Scala's separation of the class (static) fields and instance fields, in this case, makes this much more arduous than would be done with Java. One of those cases where Scala doesn't have all the advantages:
class MyClass {
// Commons logging
private static final Log clLogger = LogFactory.getLog(MyClass.class)
// java.util.logging
private static final Logger juLogger = Logger.getLogger(MyClass.class.toString)
...
}
I've looked at example of logging in Scala, and it usually looks like this:
import org.slf4j.LoggerFactory
trait Loggable {
private lazy val logger = LoggerFactory.getLogger(getClass)
protected def debug(msg: => AnyRef, t: => Throwable = null): Unit =
{...}
}
This seems independent of the concrete logging framework. While this does the job, it also introduces an extraneous lazy val in every instance that wants to do logging, which might well be every instance of the whole application. This seems much too heavy to me, in particular if you have many "small instances" of some specific type.
Is there a way of putting the logger in the object of the concrete class instead, just by using inheritance? If I have to explicitly declare the logger in the object of the class, and explicitly refer to it from the class/trait, then I have written almost as much code as if I had done no reuse at all.
Expressed in a non-logging specific context, the problem would be:
How do I declare in a trait that the implementing class must have a singleton object of type X, and that this singleton object must be accessible through method def x: X ?
I can't simply define an abstract method, because there could only be a single implementation in the class. I want that logging in a super-class gets me the super-class singleton, and logging in the sub-class gets me the sub-class singleton. Or put more simply, I want logging in Scala to work like traditional logging in Java, using static loggers specific to the class doing the logging. My current knowledge of Scala tells me that this is simply not possible without doing it exactly the same way you do in Java, without much if any benefits from using the "better" Scala.
Premature Optimization is the root of all evil
Let's be clear first about one thing: if your trait looks something like this:
trait Logger { lazy val log = Logger.getLogger }
Then what you have not done is as follows:
You have NOT created a logger instance per instance of your type
You have neither given yourself a memory nor a performance problem (unless you have)
What you have done is as follows:
You have an extra reference in each instance of your type
When you access the logger for the first time, you are probably doing some map lookup
Note that, even if you did create a separate logger for each instance of your type (which I frequently do, even if my program contains hundreds of thousands of these, so that I have very fine-grained control over my logging), you almost certainly still will neither have a performance nor a memory problem!
One "solution" is (of course), to make the companion object implement the logger interface:
object MyType extends Logger
class MyType {
import MyType._
log.info("Yay")
}
How do I declare in a trait that the
implementing class must have a
singleton object of type X, and that
this singleton object must be
accessible through method def x: X ?
Declare a trait that must be implemented by your companion objects.
trait Meta[Base] {
val logger = LoggerFactory.getLogger(getClass)
}
Create a base trait for your classes, sub-classes have to overwrite the meta method.
trait Base {
def meta: Meta[Base]
def logger = meta.logger
}
A class Whatever with a companion object:
object Whatever extends Meta[Base]
class Whatever extends Base {
def meta = Whatever
def doSomething = {
logger.log("oops")
}
}
In this way you only need to have a reference to the meta object.
We can use the Whatever class like this.
object Sample {
def main(args: Array[String]) {
val whatever = new Whatever
whatever.doSomething
}
}
I'm not sure I understand your question completely. So I apologize up front if this is not the answer you are looking for.
Define an object were you put your logger into, then create a companion trait.
object Loggable {
private val logger = "I'm a logger"
}
trait Loggable {
import Loggable._
def debug(msg: String) {
println(logger + ": " + msg)
}
}
So now you can use it like this:
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
Does this answer your question?
I think you cannot automatically get the corresponding singleton object of a class or require that such a singleton exists.
One reason is that you cannot know the type of the singleton before it is defined. Not sure, if this helps or if it is the best solution to your problem, but if you want to require some meta object to be defined with a specific trait, you could define something like:
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
I know that objects are treated pretty much like singletons in scala. However, I have been unable to find an elegant way to specify default behavior on initial instantiation. I can accomplish this by just putting code into the body of the object declaration but this seems overly hacky. Using an apply doesn't really work because it can be called multiple times and doesn't really make sense for this use case.
Any ideas on how to do this?
Classes and objects both run the code in their body upon instantiation, by design. Why is this "hacky"? It's how the language is supposed to work. If you like extra braces, you can always use them (and they'll keep local variables from being preserved and world-viewable).
object Initialized {
// Initalization block
{
val someStrings = List("A","Be","Sea")
someStrings.filter(_.contains('e')).foreach(s => println("Contains e: " + s))
}
def doSomething { println("I was initialized before you saw this.") }
}
scala> Initialized.doSomething
Contains e: Be
Contains e: Sea
I was initialized before you saw this.
scala> Initialized.someStrings
<console>:9: error: value someStrings is not a member of object Initialized
Initialized.someStrings
Rex has it right, I just wanted to point out a pattern I use a lot, that saves you from having to use vars, while avoiding namespace pollution by intermediate values.
object Foo {
val somethingFooNeeds = {
val intermediate = expensiveCalculation
val something = transform(intermediate)
something
}
}
If it makes you feel better, you can create some class with protected constructor and object will create singleton of this class:
sealed class MyClass protected (val a: String, b: Int) {
def doStuff = a + b
}
object MyObject extends MyClass("Hello", b = 1)
Also notice, that sealed stops other classes and objects to extend MyClass and protected will not allow creation of other MyClass instances.
But I personally don't see any problems with some code in the body of the object. You can also create some method like init and just call it:
object MyObject {
init()
def init() {
...
}
}
The body of object and class declarations IS the default constructor and any code placed in there will be executed upon first reference, so that is exactly the way to do it.