Scala Compiler giving error where trying to run following program.
Error:(19, 8) class Logging inherits conflicting members:
method log in trait TimestampLogger of type (msg: String)Unit and
method log in trait ShortLogger of type (msg: String)Unit
(Note: this can be resolved by declaring an override in class Logging.)
class Logging extends TimestampLogger with ShortLogger
^
trait ShortLogger {
def log (msg: String) {println(msg)}
trait TimestampLogger {
def log (msg: String) {
println("We are in Timestamp Logger")
println(new java.util.Date() )
}
}
class Logging extends TimestampLogger with ShortLogger
val a = new Logging
a.log("Log Message")
Why Stackable Modification in scala traits not suggesting the correct log method?
Why are we getting compilation error?
The error here is as message says lack of overrides.
You cannot have 2 different implementations of a method with the same signature. You have to resolve it. With traits you can have one implementation override another - this is actually required to perform trait linearization. But to be able to override you have to prove that overrides are about the same method. One way to fix it is to let methods override some base member. It always picks the "last" implementation.
trait Logger { def log(msg: String): Unit = () }
trait ShortLogger extends Logger {
override def log(msg: String) = println(msg)
}
trait TimestampLogger extends Logger {
override def log(msg: String): Unit = {
println("We are in Timestamp Logger")
println(new java.util.Date() )
}
}
// last override "wins" => ShortLogger implementation will be used
class Logging1 extends TimestampLogger with ShortLogger
// last override "wins" => TimestampLogger implementation will be used
class Logging2 extends ShortLogger with TimestampLogger
If you don't want to use last-wins, you have to reimplement the method in the place where they are conflicting:
class Logging extends TimestampLogger with ShortLogger {
override def log(msg: String) = ...
}
If you wanted to have both functionalities you would have to use a former approach + super
trait Logger { def log(msg: String): Unit = () }
trait ShortLogger extends Logger {
override def log(msg: String) = {
super.log(msg)
println(msg)
}
}
trait TimestampLogger extends Logger {
override def log(msg: String): Unit = {
super.log(msg)
println("We are in Timestamp Logger")
println(new java.util.Date())
}
}
// both will perform both loggings, but in a different order
class Logging1 extends TimestampLogger with ShortLogger
class Logging2 extends ShortLogger with TimestampLogger
Related
I want to write a family of traits whose methods should log something and a Logger trait that should be implemented in concrete Loggers and it should only be possible to mix in the above traits when a Logger is mixed in as well. I only know that a trait can depend on a class, i.e. it can only be mixed into classes who have this class as super type. What can I do?
It sounds like you need self types e.g.
trait Logger {
def log(msg: String): Unit
}
trait ConsoleLogger extends Logger {
def log(msg: String): Unit = { println(msg) }
}
trait NeedsLogger { self: Logger =>
def doSomething(): Unit = {
self.log("about to do something...")
self.log("it worked!")
}
}
object Test extends NeedsLogger with ConsoleLogger {
}
Test.doSomething()
I have a class that extends a Trait and I want to write Traits that can mix in with the class and override some of the methods.
The trait that my class is extending looks like this
trait CharSource {
def source: Iterator[Char]
def words: Iterator[String] = {
while(source.hasNext){
//Logic to get the next word from a Char Iterator
}
}
final def chars: Iterator[Char] = words.toString().toIterator
}
The class that extends CharSource
class IteratorDocumentSource(iterator: Iterator[Char]) extends CharSource {
def source = iterator
}
Now I want to write a trait to override the source def in IteratorDocutmentSource for some special behavior
trait PunctuationRemover extends Transformer {self: CharSource =>
override
/** Character source. Overriding should be in terms of `super.source` for
stackability. */
abstract val source: Iterator[Char] = {
super.source
//additional logic ...
}
}
The transformer trait that PunctioationRemover extends
trait Transformer {self: CharSource =>
protected def source: Iterator[Char]
def words: Iterator[String]
}
I get an error when making this call
new IteratorDocumentSource("Hello World!".iterator) with PunctuationRemover
Error:
An exception or error caused a run to abort:
SampleSuite$$anonfun$2$$anon$3.document$PunctuationRemover$$super$source()Lscala/collection/Iterator;
java.lang.AbstractMethodError:
SampleSuite$$anonfun$2$$anon$3.document$PunctuationRemover$$super$source()Lscala/collection/Iterator;
I referenced this post but I think my situation is a little different
Can I override a scala class method with a method from a trait?
I have a trait and a class that extends the trait. I can use the methods from the trait as follows:
trait A {
def a = ""
}
class B(s: String) extends A {
def b = a
}
However, when I use the trait's method in the constructor like this:
trait A {
def a = ""
}
class B(s: String) extends A {
def this() = this(a)
}
then the following error appears:
error: not found: value a
Is there some way to define default parameters for the construction of classes in the trait?
EDIT: To clarify the purpose: There is the akka-testkit:
class TestKit(_system: ActorSystem) extends { implicit val system = _system }
And each test looks like this:
class B(_system: ActorSystem) extends TestKit(_system) with A with ... {
def this() = this(actorSystem)
...
}
because I want to create common creation of the ActorSystem in A:
trait A {
val conf = ...
def actorSystem = ActorSystem("MySpec", conf)
...
}
It's a little bit tricky because of Scala initialization order. The simplest solution I found is to define a companion object for your class B with apply as factory method:
trait A {
def a = "aaaa"
}
class B(s: String) {
println(s)
}
object B extends A {
def apply() = new B(a)
def apply(s: String) = new B(s)
}
I have a question concerning Scala override (as my title suggests)
Now I have the following classes/traits:
trait FSM {def transitionGraph:Map[String,(JsValue,FSM)]
abstract class AClass: FSM { def transitionGraph }
class Class extends AClass{ override def transitionGraph ... } <-- Wont work
trait OverrideTrait extends AClass { abstract override def transitionGraph } <-- works
class NewClass extends OverrideTrait { } <--- Works, I can use the overridden transitionGraph
My question is: Why can I not override things from an abstract class. Is it because I am never allowed to instantiate an abstract class. Thus the behavior :
val AClass class = new Class
is never allowed to happen?
Thanks.
There seems to be a lot of stuff omitted from the code you've given, so I'm not sure I get the question, but here's something similar that does compile:
trait FSM { def transitionGraph: String }
abstract class AClass extends FSM { def transitionGraph: String }
class Class extends AClass { override def transitionGraph = ??? }
trait OverrideTrait extends AClass { override def transitionGraph = ??? }
class NewClass extends OverrideTrait { }
Does this help at all?
Your code example wouldn't compile. But it should work once you corrected a few things:
trait FSM {def transitionGraph:Map[String,(JsValue,FSM)]}
abstract class AbstractClass extends FSM { def transitionGraph }
class ConcreteClass extends AbstractClass{ def transitionGraph = ??? }
val someClass: AbstractClass = new ConcreteClass
I'd like some help sorting out this scenario. I have an Akka actor where I want to inject a dependency, in this case RemoteFetcher, which I would also like mock in my tests. Like so:
main/src/scala/mypackage/Services.scala
package mypackage
import RemoteFetcherFileSystem._
trait RemoteFetcher {
def fetch( path:String ): Future[Stream[String]]
}
class MyRemoteResourceActor extends Actor with ActorLogging {
def fetchRemote( path:String ) = implicitly[RemoteFetcher].fetch( path )
def receive = {
case FetchRemoteResource( path ) => fetchRemote( path ).map( _.foreach( sender ! _ ) )
}
}
For this to work I have an implicit object that I import into the file above. Would look something like this:
implicit object RemoteFetcherFileSystem extends RemoteFetcher {
def fetchRemote( path:String ) = Future[Stream[String]] { ... reading from file system ... }
}
Now in my tests I have TestActor from the akka-testkit. Here I want to instead import my mock dependency:
implicit object RemoteFetcherMock extends RemoteFetcher {
def fetchRemote( path:String ) = Future[Stream[String]] { ... mock implementation ... }
}
My problem is that to compile Services.scala I need to import the implicit object. But how do I go about to shadow/override this in my test-files. The reason I'm not using implicit arguments is that I want to avoid having to modify all my actors constructor arguments.
I when looking around and reading up on the type class dependency injection pattern and I get it to work according to the tutorials, but I don't get it to work when I want to test and override like in my example.
I'm not sure how to do it with implicits, but typically one could inject instead like so:
trait RemoteFetcherComponent {
def remoteFetcher: RemoteFetcher
trait RemoteFetcher {
def fetch(path: String): Future[Stream[String]]
}
}
trait RemoteFetcherFileSystemComponent extends RemoteFetcherComponent {
val remoteFetcher = RemoteFetcherFileSystem
object RemoteFetcherFileSystem extends RemoteFetcher {
def fetch(path: String): Future[Stream[String]] = ???
}
}
class MyRemoteResourceActor extends Actor with ActorLogging with RemoteFetcherFileSystemComponent {
def fetchRemote(path: String) = remoteFetcher.fetch(path)
def receive = {
case FetchRemoteResource(path) => fetchRemote(path).map( _.foreach(sender ! _))
}
}
val myRemoteResourceActor = new MyRemoteResourceActor()
And then a test value would be defined like so:
trait RemoteFetcherMockComponent extends RemoteFetcherComponent {
def remoteFetcher = RemoteFetcherMock
object RemoteFetcherMock extends RemoteFetcher {
def fetch(path: String): Future[Stream[String]] = ???
}
}
val myMockedResourceActor = new MyRemoteResourceActor with RemoteFetcherMockComponent {
override val remoteFetcher = super[RemoteFetcherMockComponent].remoteFetcher
}
The reason you are having an issue with implicits is because the way you're using it is no different from simply using def fetchRemote(path: String) = RemoteFetcherFileSystem.fetch(path). With the import, you've defined the implementation, rather than allowed it to be injected later.
You could also change the implicitly to an implicit parameter:
trait RemoteFetcher {
def fetch(path: String): Future[Stream[String]]
}
object RemoteFetcher {
implicit val fetcher = RemoteFetcherFileSystem
}
class MyRemoteResourceActor extends Actor with ActorLogging {
def fetchRemote(path: String)(implicit remoteFetcher: RemoteFetcher) = remoteFetcher.fetch(path)
def receive = {
case FetchRemoteResource(path) => fetchRemote(path).map( _.foreach(sender ! _))
}
}
Then you could override the implicit that is resolved in the companion object of RemoteFetcher by simply importing RemoteFetcherMock.
See this post for more information about implicit parameter resolution precedence rules.