- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Troubles with Traits
Mon, 2011-12-05, 20:33
This is my first time using traits, but I cannot seem to achieve what I
want. I want a trait "Emitter" I can use use to emit messages with
println() and with org.slf4j.Logger. Currently this looks like
trait Emitter {
var logger:Logger
def emit(message:String) = {
logger.info(message)
println(message)
}
}
but when I try to use it like
object Archive extends Emitter {
val properties = Properties.getScriptProperties(); // must call
before getLogger() - EK
logger = Properties.getLogger(getClass())
src\Archive.scala:31: error: object creation impossible, since variable
logger in trait Emitter of type org.slf4j.Logger is not defined
(Note that variables need to be initialized to be defined)
object Archive extends Emitter {
^
one error found
Compilation failed, exitValue = 1
Is there some way to do what I want?
Cheers, Eric
Mon, 2011-12-05, 20:57
#2
Re: Troubles with Traits
On 12/05/2011 08:34 PM, Eric Kolotyluk wrote:
In Emitter, try to initialize logger:
trait Emitter {
var logger:Logger = null
def emit(message:String) = {
logger.info(message)
println(message)
}
}
If you really want logger to be an abstract var, you'll need a setter as well in the subclass:
object Archive extends Emitter {
var logger = null
def logger_=(v: Logger):Unit = { logger = v}
}
4EDD1CB9 [dot] 9080407 [at] gmail [dot] com" type="cite">This is my first time using traits, but I cannot seem to achieve what I want. I want a trait "Emitter" I can use use to emit messages with println() and with org.slf4j.Logger. Currently this looks like
trait Emitter {
var logger:Logger
def emit(message:String) = {
logger.info(message)
println(message)
}
}
but when I try to use it like
object Archive extends Emitter {
val properties = Properties.getScriptProperties(); // must call before getLogger() - EK
logger = Properties.getLogger(getClass())
src\Archive.scala:31: error: object creation impossible, since variable logger in trait Emitter of type org.slf4j.Logger is not defined
(Note that variables need to be initialized to be defined)
object Archive extends Emitter {
^
one error found
Compilation failed, exitValue = 1
Is there some way to do what I want?
In Emitter, try to initialize logger:
trait Emitter {
var logger:Logger = null
def emit(message:String) = {
logger.info(message)
println(message)
}
}
If you really want logger to be an abstract var, you'll need a setter as well in the subclass:
object Archive extends Emitter {
var logger = null
def logger_=(v: Logger):Unit = { logger = v}
}
-- Andreas Joseph Krogh- mob: +47 909 56 963 Senior Software Developer / CTO - OfficeNet AS - http://www.officenet.no Public key: http://home.officenet.no/~andreak/public_key.asc
Mon, 2011-12-05, 21:27
#3
Re: Troubles with Traits
On Mon, Dec 5, 2011 at 17:34, Eric Kolotyluk wrote:
> This is my first time using traits, but I cannot seem to achieve what I
> want. I want a trait "Emitter" I can use use to emit messages with println()
> and with org.slf4j.Logger. Currently this looks like
>
> trait Emitter {
> var logger:Logger
> def emit(message:String) = {
> logger.info(message)
> println(message)
> }
> }
This has declared "logger" as abstract. If you want it unitialized,
write it like this:
var logger: Logger = _
However, it's best to declare it as
def logger: Logger // abstact
And then write this in Archive:
override val logger = Properties.getLogger(getClass()) // maybe lazy
val if it logging might not happen at all
You can override a def with a val (but not the other way around). The
def is appropriate for the trait definition, because all the trait
wants is a getter.
Mon, 2011-12-05, 21:37
#4
Re: Troubles with Traits
On 2011-12-05 11:42 AM, Erik Osheim wrote:
> On Mon, Dec 05, 2011 at 11:34:17AM -0800, Eric Kolotyluk wrote:
>> trait Emitter {
>> var logger:Logger
>> def emit(message:String) = {
>> logger.info(message)
>> println(message)
>> }
>> }
>>
>> but when I try to use it like
>>
>> object Archive extends Emitter {
>> val properties = Properties.getScriptProperties(); // must call
>> before getLogger() - EK
>> logger = Properties.getLogger(getClass())
> I think you probably want to make logger be defined with "val" not
> "var"; you'd also want to put "val" before logger in your Archive
> object.
>
> Also, since you're not using the result of getScriptProperties() you
> might as well not save the result (to make it more obvious what's going
> on).
>
Mon, 2011-12-05, 21:47
#5
Re: Troubles with Traits
On 2011-12-05 11:50 AM, Andreas Joseph Krogh wrote:
While this works perfectly well, is this the most Scala-like way to do things, or is there a more elegant way to do this sort of thing?
I'm not sure what advantage this has?
4EDD207A [dot] 2070200 [at] officenet [dot] no" type="cite"> On 12/05/2011 08:34 PM, Eric Kolotyluk wrote:OK, now I feel stupid. That works perfectly - thanks :-) Where do I send the beer to Andreas?4EDD1CB9 [dot] 9080407 [at] gmail [dot] com" type="cite">This is my first time using traits, but I cannot seem to achieve what I want. I want a trait "Emitter" I can use use to emit messages with println() and with org.slf4j.Logger. Currently this looks like
trait Emitter {
var logger:Logger
def emit(message:String) = {
logger.info(message)
println(message)
}
}
but when I try to use it like
object Archive extends Emitter {
val properties = Properties.getScriptProperties(); // must call before getLogger() - EK
logger = Properties.getLogger(getClass())
src\Archive.scala:31: error: object creation impossible, since variable logger in trait Emitter of type org.slf4j.Logger is not defined
(Note that variables need to be initialized to be defined)
object Archive extends Emitter {
^
one error found
Compilation failed, exitValue = 1
Is there some way to do what I want?
In Emitter, try to initialize logger:
trait Emitter {
var logger:Logger = null
def emit(message:String) = {
logger.info(message)
println(message)
}
}
While this works perfectly well, is this the most Scala-like way to do things, or is there a more elegant way to do this sort of thing?
4EDD207A [dot] 2070200 [at] officenet [dot] no" type="cite">
If you really want logger to be an abstract var, you'll need a setter as well in the subclass:
object Archive extends Emitter {
var logger = null
def logger_=(v: Logger):Unit = { logger = v}
}
I'm not sure what advantage this has?
4EDD207A [dot] 2070200 [at] officenet [dot] no" type="cite">-- Andreas Joseph Krogh andreak [at] officenet [dot] no" rel="nofollow"><andreak@officenet.no> - mob: +47 909 56 963 Senior Software Developer / CTO - OfficeNet AS - http://www.officenet.no Public key: http://home.officenet.no/~andreak/public_key.asc
Mon, 2011-12-05, 21:47
#6
Re: Troubles with Traits
On 12/05/2011 09:28 PM, Eric Kolotyluk wrote:
Send it to yourself each time you accomplish new cool stuff in Scala-land:-)
Having an abstract var in a trait makes absolutely no sense to me. There's no advantage unless you actually want "write-access" to the variable, and not just a getter (a def, like Daniel suggested).
If all you're after is to have (read) access to "logger" from Emitter, but delegate the initialization/implementation to the subclass, Daniel's suggestion of having a def in Emitter and a val in subclass is the "scala-way".
4EDD2962 [dot] 1000808 [at] gmail [dot] com" type="cite"> On 2011-12-05 11:50 AM, Andreas Joseph Krogh wrote:4EDD207A [dot] 2070200 [at] officenet [dot] no" type="cite"> On 12/05/2011 08:34 PM, Eric Kolotyluk wrote:OK, now I feel stupid. That works perfectly - thanks :-) Where do I send the beer to Andreas?4EDD1CB9 [dot] 9080407 [at] gmail [dot] com" type="cite">This is my first time using traits, but I cannot seem to achieve what I want. I want a trait "Emitter" I can use use to emit messages with println() and with org.slf4j.Logger. Currently this looks like
trait Emitter {
var logger:Logger
def emit(message:String) = {
logger.info(message)
println(message)
}
}
but when I try to use it like
object Archive extends Emitter {
val properties = Properties.getScriptProperties(); // must call before getLogger() - EK
logger = Properties.getLogger(getClass())
src\Archive.scala:31: error: object creation impossible, since variable logger in trait Emitter of type org.slf4j.Logger is not defined
(Note that variables need to be initialized to be defined)
object Archive extends Emitter {
^
one error found
Compilation failed, exitValue = 1
Is there some way to do what I want?
In Emitter, try to initialize logger:
trait Emitter {
var logger:Logger = null
def emit(message:String) = {
logger.info(message)
println(message)
}
}
Send it to yourself each time you accomplish new cool stuff in Scala-land:-)
4EDD2962 [dot] 1000808 [at] gmail [dot] com" type="cite"> While this works perfectly well, is this the most Scala-like way to do things, or is there a more elegant way to do this sort of thing?
4EDD207A [dot] 2070200 [at] officenet [dot] no" type="cite">
If you really want logger to be an abstract var, you'll need a setter as well in the subclass:
object Archive extends Emitter {
var logger = null
def logger_=(v: Logger):Unit = { logger = v}
}
I'm not sure what advantage this has?
Having an abstract var in a trait makes absolutely no sense to me. There's no advantage unless you actually want "write-access" to the variable, and not just a getter (a def, like Daniel suggested).
If all you're after is to have (read) access to "logger" from Emitter, but delegate the initialization/implementation to the subclass, Daniel's suggestion of having a def in Emitter and a val in subclass is the "scala-way".
-- Andreas Joseph Krogh- mob: +47 909 56 963 Senior Software Developer / CTO - OfficeNet AS - http://www.officenet.no Public key: http://home.officenet.no/~andreak/public_key.asc
Mon, 2011-12-05, 21:57
#7
Re: Troubles with Traits
On 2011-12-05 12:15 PM, Daniel Sobral wrote:
> On Mon, Dec 5, 2011 at 17:34, Eric Kolotyluk wrote:
>> This is my first time using traits, but I cannot seem to achieve what I
>> want. I want a trait "Emitter" I can use use to emit messages with println()
>> and with org.slf4j.Logger. Currently this looks like
>>
>> trait Emitter {
>> var logger:Logger
>> def emit(message:String) = {
>> logger.info(message)
>> println(message)
>> }
>> }
> This has declared "logger" as abstract. If you want it unitialized,
> write it like this:
>
> var logger: Logger = _
var logger: Logger = null // also works fine
>
> However, it's best to declare it as
>
> def logger: Logger // abstact
>
> And then write this in Archive:
>
> override val logger = Properties.getLogger(getClass()) // maybe lazy
> val if it logging might not happen at all
OK, I can understand how that works, and it does seem more consistent
with how traits are documented.
I tested with 'override lazy val logger =
Properties.getLogger(getClass())' and it works great, as it is likely
logging might not happen.
>
> You can override a def with a val (but not the other way around). The
> def is appropriate for the trait definition, because all the trait
> wants is a getter.
Thanks for the cool knowledge. This was not apparent from the
documentation I was reading, but seems to be a nice pattern.
Cheers, Eric
Mon, 2011-12-05, 22:17
#8
Re: Troubles with Traits
On 2011-12-05 12:37 PM, Eric Kolotyluk wrote:
> On 2011-12-05 12:15 PM, Daniel Sobral wrote:
>> On Mon, Dec 5, 2011 at 17:34, Eric
>> Kolotyluk wrote:
>>> This is my first time using traits, but I cannot seem to achieve what I
>>> want. I want a trait "Emitter" I can use use to emit messages with
>>> println()
>>> and with org.slf4j.Logger. Currently this looks like
>>>
>>> trait Emitter {
>>> var logger:Logger
>>> def emit(message:String) = {
>>> logger.info(message)
>>> println(message)
>>> }
>>> }
>> This has declared "logger" as abstract. If you want it unitialized,
>> write it like this:
>>
>> var logger: Logger = _
>
> var logger: Logger = null // also works fine
>
>>
>> However, it's best to declare it as
>>
>> def logger: Logger // abstact
>>
>> And then write this in Archive:
>>
>> override val logger = Properties.getLogger(getClass()) // maybe lazy
>> val if it logging might not happen at all
>
> OK, I can understand how that works, and it does seem more consistent
> with how traits are documented.
>
> I tested with 'override lazy val logger =
> Properties.getLogger(getClass())' and it works great, as it is likely
> logging might not happen.
OK, this does not work as I expected. My logs show
[2011-12-05 13:01:23,890] INFO [main] -
Emitter$class.emit(Emitter.scala:41) - creating archive
Intersystem\archive\2011-12-05 21-01-23.889.7z
[2011-12-05 13:01:25,713] INFO [main] -
Emitter$class.emit(Emitter.scala:41) - added Intersystem\dump\2011-12-05
21-01-23.545
Whereas what I wanted was
[2011-12-05 13:01:23,890] INFO [main] -
Archive$class.apply(Archive.scala:48) - creating archive
Intersystem\archive\2011-12-05 21-01-23.889.7z
[2011-12-05 13:01:25,713] INFO [main] -
Archive$class.apply(Archive.scala:52) - added
Intersystem\dump\2011-12-05 21-01-23.545
How does
object Archive extends Emitter {
val properties = Properties.getScriptProperties(); // must call
before getLogger() - EK
override lazy val logger = Properties.getLogger(getClass())
pick up the logger for Emitter instead of Archive? How can I get Emitter
to use the logger for Archive?
Cheers, Eric
>
>>
>> You can override a def with a val (but not the other way around). The
>> def is appropriate for the trait definition, because all the trait
>> wants is a getter.
> Thanks for the cool knowledge. This was not apparent from the
> documentation I was reading, but seems to be a nice pattern.
>
> Cheers, Eric
Mon, 2011-12-05, 23:17
#9
Re: Troubles with Traits
Am 05.12.2011 21:37, schrieb Eric Kolotyluk:
> On 2011-12-05 12:15 PM, Daniel Sobral wrote:
>> var logger: Logger = _
>
> var logger: Logger = null // also works fine
It compiles to the same code. The difference is that the first version
makes it more clear that you see it as uninitialized vs. initialized
with the special value null (which you should try to avoid anyway).
But of course both versions are not "fine", as they leave you vulnerable
to null pointer excepions if you extend your trait and forget to
initialize logger (which can take quite some time to diagnose if the
logger is intended to log only exceptional behaviour, and then it will
be doubly hard to debug the problem). The version recommended by Daniel
using def and override val will not even compile in that case, which
is the point of a statically typed language.
- Florian.
Tue, 2011-12-06, 15:27
#10
Re: Troubles with Traits
On Mon, Dec 5, 2011 at 19:12, Eric Kolotyluk wrote:
>
> OK, this does not work as I expected. My logs show
>
> [2011-12-05 13:01:23,890] INFO [main] -
> Emitter$class.emit(Emitter.scala:41) - creating archive
> Intersystem\archive\2011-12-05 21-01-23.889.7z
> [2011-12-05 13:01:25,713] INFO [main] -
> Emitter$class.emit(Emitter.scala:41) - added Intersystem\dump\2011-12-05
> 21-01-23.545
>
> Whereas what I wanted was
>
> [2011-12-05 13:01:23,890] INFO [main] -
> Archive$class.apply(Archive.scala:48) - creating archive
> Intersystem\archive\2011-12-05 21-01-23.889.7z
> [2011-12-05 13:01:25,713] INFO [main] -
> Archive$class.apply(Archive.scala:52) - added Intersystem\dump\2011-12-05
> 21-01-23.545
>
> How does
>
>
> object Archive extends Emitter {
> val properties = Properties.getScriptProperties(); // must call before
> getLogger() - EK
> override lazy val logger = Properties.getLogger(getClass())
>
> pick up the logger for Emitter instead of Archive? How can I get Emitter to
> use the logger for Archive?
And "object" is a not a class. Try replacing "object" with "class"
there, and then writing:
object Archive extends Archive // object Archive is of class Archive
Tue, 2011-12-06, 17:47
#11
Re: Troubles with Traits
On 2011-12-06 6:18 AM, Daniel Sobral wrote:
Here is what I have, but it does not fix the problem
class Restore extends Emitter {
val properties = Properties.getScriptProperties(); // must call before getLogger() - EK
override lazy val logger = Properties.getLogger(getClass())
. . .
}
object Restore extends Restore // object Restore extends class Restore
[2011-12-06 08:24:31,438] INFO [main] - Emitter$class.emitInfo(Emitter.scala:42) - extracted Intersystem\dump\2011-12-06 07-48-03.697\hibernate.sql
[2011-12-06 08:24:31,439] INFO [main] - Emitter$class.emitInfo(Emitter.scala:42) - restoring Intersystem\dump\2011-12-06 07-48-03.697\hibernate.sql
Maybe it is not possible make it do what I want?
Cheers, Eric
zczPdviqnagJarBw [at] mail [dot] gmail [dot] com" type="cite">On Mon, Dec 5, 2011 at 19:12, Eric Kolotylukwrote: OK, this does not work as I expected. My logs show [2011-12-05 13:01:23,890] INFO [main] - Emitter$class.emit(Emitter.scala:41) - creating archive Intersystem\archive\2011-12-05 21-01-23.889.7z [2011-12-05 13:01:25,713] INFO [main] - Emitter$class.emit(Emitter.scala:41) - added Intersystem\dump\2011-12-05 21-01-23.545 Whereas what I wanted was [2011-12-05 13:01:23,890] INFO [main] - Archive$class.apply(Archive.scala:48) - creating archive Intersystem\archive\2011-12-05 21-01-23.889.7z [2011-12-05 13:01:25,713] INFO [main] - Archive$class.apply(Archive.scala:52) - added Intersystem\dump\2011-12-05 21-01-23.545 How does object Archive extends Emitter { val properties = Properties.getScriptProperties(); // must call before getLogger() - EK override lazy val logger = Properties.getLogger(getClass()) pick up the logger for Emitter instead of Archive? How can I get Emitter to use the logger for Archive?And "object" is a not a class. Try replacing "object" with "class" there, and then writing: object Archive extends Archive // object Archive is of class Archive
Here is what I have, but it does not fix the problem
class Restore extends Emitter {
val properties = Properties.getScriptProperties(); // must call before getLogger() - EK
override lazy val logger = Properties.getLogger(getClass())
. . .
}
object Restore extends Restore // object Restore extends class Restore
[2011-12-06 08:24:31,438] INFO [main] - Emitter$class.emitInfo(Emitter.scala:42) - extracted Intersystem\dump\2011-12-06 07-48-03.697\hibernate.sql
[2011-12-06 08:24:31,439] INFO [main] - Emitter$class.emitInfo(Emitter.scala:42) - restoring Intersystem\dump\2011-12-06 07-48-03.697\hibernate.sql
Maybe it is not possible make it do what I want?
Cheers, Eric
Tue, 2011-12-06, 20:03
#12
Re: Troubles with Traits
On 6 December 2011 16:32, Eric Kolotyluk <eric.kolotyluk@gmail.com> wrote:
Hi Eric
You might want to take a look at the Grizzled slf4j wrapper.
Specifically:
https://github.com/bmc/grizzled-slf4j/blob/master/src/main/scala/grizzled/slf4j/slf4j.scala
If I understand correctly, the "Logging" trait seems to do what you want and should either be a useful example or you should be able to just mix it in wherever you wish to use it (though you will need to include slf4j and logback or some other backend as dependencies).
I'm not sure why your specific example isn't working but you shouldn't need to override the logger definition in classes extending the trait - dynamic dispatch should mean the class returned is the one of the subclass I thought. Maybe there's something lurking in "properties" which seems to be your equivalent of a LogFactory that causes this to behave differently? Or maybe you mean "properties.getLogger" not "Properties.getLogger"?
Cheers
Brian
Maybe it is not possible make it do what I want?
Cheers, Eric
Hi Eric
You might want to take a look at the Grizzled slf4j wrapper.
Specifically:
https://github.com/bmc/grizzled-slf4j/blob/master/src/main/scala/grizzled/slf4j/slf4j.scala
If I understand correctly, the "Logging" trait seems to do what you want and should either be a useful example or you should be able to just mix it in wherever you wish to use it (though you will need to include slf4j and logback or some other backend as dependencies).
I'm not sure why your specific example isn't working but you shouldn't need to override the logger definition in classes extending the trait - dynamic dispatch should mean the class returned is the one of the subclass I thought. Maybe there's something lurking in "properties" which seems to be your equivalent of a LogFactory that causes this to behave differently? Or maybe you mean "properties.getLogger" not "Properties.getLogger"?
Cheers
Brian
Thu, 2011-12-08, 20:41
#13
Re: Troubles with Traits
On 2011-12-06 10:15 AM, Brian Smith wrote:
OK, I took a look at it, but the solution does not seem obvious.
I really do mean Properties.getLogger() as that is Java code I wrote to get a logger as it has to be able to work as a static method. Basically, getting the logger this way ensures that the .properties file with all the logging properties is read first and the logging system is configured properly before getting a new logger. Also, ensures the logger is a singleton by caching them in a HashMap.
I am using a log4j back-end with slf4j.
I guess the other way of doing this would be to configure a special console logger and log Info or higher to the command like and log more verbose stuff to the file logger. This would eliminate the need for my Emitter trait.
Cheers, Eric
CAE8w+W10j9Ywreu0YCHSevpWT720BbSMTNSJFr8UGq9kX3fJ3Q [at] mail [dot] gmail [dot] com" type="cite">On 6 December 2011 16:32, Eric Kolotyluk <eric [dot] kolotyluk [at] gmail [dot] com" rel="nofollow">eric.kolotyluk@gmail.com> wrote:
Maybe it is not possible make it do what I want?
Cheers, Eric
Hi Eric
You might want to take a look at the Grizzled slf4j wrapper.
Specifically:
https://github.com/bmc/grizzled-slf4j/blob/master/src/main/scala/grizzled/slf4j/slf4j.scala
If I understand correctly, the "Logging" trait seems to do what you want and should either be a useful example or you should be able to just mix it in wherever you wish to use it (though you will need to include slf4j and logback or some other backend as dependencies).
OK, I took a look at it, but the solution does not seem obvious.
CAE8w+W10j9Ywreu0YCHSevpWT720BbSMTNSJFr8UGq9kX3fJ3Q [at] mail [dot] gmail [dot] com" type="cite">
I'm not sure why your specific example isn't working but you shouldn't need to override the logger definition in classes extending the trait - dynamic dispatch should mean the class returned is the one of the subclass I thought. Maybe there's something lurking in "properties" which seems to be your equivalent of a LogFactory that causes this to behave differently? Or maybe you mean "properties.getLogger" not "Properties.getLogger"?
I really do mean Properties.getLogger() as that is Java code I wrote to get a logger as it has to be able to work as a static method. Basically, getting the logger this way ensures that the .properties file with all the logging properties is read first and the logging system is configured properly before getting a new logger. Also, ensures the logger is a singleton by caching them in a HashMap.
I am using a log4j back-end with slf4j.
I guess the other way of doing this would be to configure a special console logger and log Info or higher to the command like and log more verbose stuff to the file logger. This would eliminate the need for my Emitter trait.
Cheers, Eric
CAE8w+W10j9Ywreu0YCHSevpWT720BbSMTNSJFr8UGq9kX3fJ3Q [at] mail [dot] gmail [dot] com" type="cite">
Cheers
Brian
Fri, 2011-12-09, 00:41
#14
Re: Troubles with Traits
Hi Eric
I really do mean Properties.getLogger() as that is Java code I wrote to get a logger as it has to be able to work as a static method. Basically, getting the logger this way ensures that the .properties file with all the logging properties is read first and the logging system is configured properly before getting a new logger. Also, ensures the logger is a singleton by caching them in a HashMap.
You shouldn't need to do this, log4j will take care of caching and configuring for you. Subsequent requests to the factory for the same named logger will get the same logger object. (Under the hood there'll be one logger object per name but if that has no specific configuration it will just link to the first one above it in the hierarchy that does).
There are a few different ways to make log4j find it's configuration without needing to force it programmatically - the simplest is to start the jvm with -Dlog4j.configuration=log4j.properties (or log4j.xml) and make sure that file is on the classpath. There's a description here of the Default Initialization Procedure.
If your Properties code is only doing the management of a logger singleton and forcing configuration load, you can likely do away with it completely - it might be the reason you're getting the wrong logger object, and I can't replicate your problem using the default initialization for log4j.
I've uploaded a simple example to github which seems to do what you want.
I guess the other way of doing this would be to configure a special console logger and log Info or higher to the command like and log more verbose stuff to the file logger. This would eliminate the need for my Emitter trait.
You can just log to the appropriate levels as normal and through configuration attach a LevelRangeFilter on your console appender to make sure that only INFO and above show there. This avoids needing to have special loggers or to remember to use them. To do this though, you need to use xml to configure log4j, for some reason filters aren't supported in properties files.
Hope this helps
Brian
On Mon, Dec 05, 2011 at 11:34:17AM -0800, Eric Kolotyluk wrote:
> trait Emitter {
> var logger:Logger
> def emit(message:String) = {
> logger.info(message)
> println(message)
> }
> }
>
> but when I try to use it like
>
> object Archive extends Emitter {
> val properties = Properties.getScriptProperties(); // must call
> before getLogger() - EK
> logger = Properties.getLogger(getClass())
I think you probably want to make logger be defined with "val" not
"var"; you'd also want to put "val" before logger in your Archive
object.
Also, since you're not using the result of getScriptProperties() you
might as well not save the result (to make it more obvious what's going
on).