Initializing traits within a trait in scala - scala

In Scala in Depth there is this example:
trait Logger {
def log(category: String, msg: String) : Unit = {
println(msg)
}
}
trait DataAccess {
def query[A](in: String) : A = {
...
}
}
trait LoggedDataAccess {
val logger = new Logger
val dao = new DataAccess
def query[A](in: String) : A = {
logger.log("QUERY", in)
dao.query(in)
}
}
I am a little confused by the initialization of Logger and DataAccess in the trait LoggedDataAccess. In the REPL, when I type out this code, I get the following exception:
error: trait Logger is abstract; cannot be instantiated
val logger = new Logger
Can a trait actually be initialized like that?

Trait can't be instantiated, but you can create an instance of anonymous implementation of trait:
scala> trait Test
defined trait Test
scala> new Test
<console>:9: error: trait Test is abstract; cannot be instantiated
new Test
^
scala> new Test{}
res0: Test = $anon$1#7fafd333
scala> new Object with Test
res1: Test = $anon$1#4fe11d82
new Test{} and new Object with Test means the same. They create new anonymous class and instantiate it right away.

Related

Mixins in Scala 3

I am working on upgrading some code from Scala 2.13 to Scala 3 and I came across some differences with trait mixins with inner traits having same names.
This code compiles in Scala 2.13:
trait First {
val first: Service
trait Service {
def someMethod(): Int
}
}
trait LiveFirst extends First {
override val first: Service = new Service {
override def someMethod(): Int = 1
}
}
trait Second {
val second: Service
trait Service {
def someMethod(): Int
}
}
trait LiveSecond extends Second {
override val second: Service = new Service {
override def someMethod(): Int = 2
}
}
type Mixed = First with Second
val mixed: Mixed = new LiveFirst with LiveSecond
But fails with following compiler error in Scala 3:
[error] 32 |val mixed: Mixed = new LiveFirst with LiveSecond
[error] | ^
[error] |error overriding trait Service in trait First;
[error] | trait Service in trait Second cannot be used here - class definitions cannot be overridden
What exactly has changed here?

Scalamock: Mocking a generic case class results in type mismatch

I'm using Mongodb as persistence in my application and I'm currently writing test for my code. My CUT looks as following
implicit def storageHandler[M[_]: Monad](
implicit mongoDatabase: MongoDatabase
) = new Storage.Handler[M] {
override def store(order: Order): M[Unit] = Monad[M].pure {
val collection: MongoCollection[Document] = mongoDatabase.getCollection("order")
val document: Document = Document(order.asJson.toString)
collection.insertOne(document).subscribe((x: Completed) => ())
}
}
My mock is getting properly injected by using implicits. I'm mocking the getCollection call which on it's own should result in another mock, this time of type
MongoCollection[org.mongodb.scala.bson.collection.immutable.Document]
So what I'm doing is the following
val mongoCollection: MongoCollection[Document] = mock[MongoCollection[Document]]
(mongoDatabase.getCollection[Document] _).expects("order").once().returning(mongoCollection)
But this result in the following error
type mismatch;
[error] found : com.mongodb.async.client.MongoCollection[TResult]
[error] required: com.mongodb.async.client.MongoCollection[org.mongodb.scala.bson.collection.immutable.Document]
[error] val mongoCollection: MongoCollection[Document] = mock[MongoCollection[Document]]
TResult is the generic parameter from the mongoCollection, which looks like this:
case class MongoCollection[TResult](private val wrapped: JMongoCollection[TResult]) {
....
}
It seems that the generic parameter is not properly "adjusted" (I'm not sure how to call it) to Document
Specifying the type parameter upfront should work, or, if your interface is fully abstract, you can use a Proxy mock for that:
import org.scalamock.scalatest.MixedMockFactory
import org.scalatest.{FlatSpec, Matchers}
import scala.reflect.ClassTag
class Issue170Test extends FlatSpec with Matchers with MixedMockFactory {
behavior of "ScalaMock"
it should "mock this" in {
class Foo[T: ClassTag]
"val m = mock[Foo[Nothing]]" should compile // this one fails :(
}
trait TotallyAbstract[T] {
def foo: Int
def bar: T
}
it should "work with this workaround" in {
class Foo[T: ClassTag]
abstract class Foo2 extends Foo[Int] // workaround: specify type parameter
"val m = mock[Foo2]" should compile
"val m2 = Proxy.mock[TotallyAbstract[Int]]" should compile
}
}

overriding implicit abstract members in a trait - injection of implicit dependencies (type class instances) - how to make it work?

The code below fails to compile.
The purpose of this code is to inject the implicit dependencies into UseImplicit.
In other words, it is a dependency injection for type class instances.
trait StuffProvider[T]{
implicit val provideStuff:() => T
}
trait UseImplicit{
implicit val gimmiString: StuffProvider[String] // implicit dependency
implicit val gimmiInt: StuffProvider[Int]
def foo[T:StuffProvider]() :T = implicitly[StuffProvider[T]].provideStuff()
}
object Main{
object StringProvider extends StuffProvider[String]{
implicit val provideStuff: () => String= () => "bla"
}
object IntProvider extends StuffProvider[Int]{
implicit val provideStuff: () => Int= () => 42
}
object UI extends UseImplicit {
implicit val gimmiString=StringProvider // injection
implicit val gimmiInt=IntProvider
}
val f:Int=UI.foo[Int]() // Error:(27, 15) could not find implicit value for evidence parameter of type StuffProvider[T]
}
but this compiles just fine :
trait UseImplicit2{
implicit val gimmiString: String
def foo() :String = implicitly[String]
}
object Main2{
object UI extends UseImplicit2 {
override implicit val gimmiString:String = "s"
}
val f=UI.foo() // this compiles just fine
}
I don't see what is the difference between the two codes, they have the same structure.
Why does the second compile and the first not ?
How can I make the first compile ?
The goal is that I can inject the implicits into a realization of UseImplicits. So that I can provide several realizations (testing, production).
Scala Fiddle is here : https://scalafiddle.io/sf/dm3OJSF/1
Importing UI implicits (by import UI._) into current scope, right before calling UI.foo(), should fix your issue.
You can inject the desired UseImplicit (e.g into a Foo class) and use it as:
case class Foo(ui: UseImplicit) {
import ui._
val f: Int = ui.foo[Int]() //Use your injected `UseImplicit`
}

Slick: CRUD extension: How to encapsulate implicit mapping:BaseColumnType[T]

There is the following API for Slick CRUD (Slick-2.1.0, Scala-2.11.4):
trait HasId {
type Id
def id: Option[Id]
}
trait HasIdColumn[E <: HasId] {
def id: scala.slick.lifted.Column[E#Id]
}
trait SlickExtensions {
val driver: scala.slick.driver.JdbcProfile
import driver.simple._
trait BaseDAO[T <: Table[E], E] {
val query: TableQuery[T]
}
trait HasIdActions[T <: Table[E] with HasIdColumn[E], E <: HasId]
extends BaseDAO[T, E] {
//line L1: this implicit val is needed to execute query.filter(_.id === id)
// what can be done in order to save the user from the necessity
// to override this value?
implicit val mappingId: BaseColumnType[E#Id]
def findById(id: E#Id)(implicit session: Session): Option[E] =
query.filter(_.id === id).firstOption
...
}
}
I apply this SlickExtensions as follows:
case class Entity(id: Option[Long] = None, value: String) extends HasId {
type Id = Long }
trait EntityComponent extends SlickExtensions {
import driver.simple._
class EntitiesTable(tag: Tag) extends Table[Entity](tag, "entities")
with HasIdColumn[Entity] {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def value = column[String]("value", O.NotNull)
def * = (id.?, value) <>(Entity.tupled, Entity.unapply)
}
object Entities extends HasIdActions[EntitiesTable, Entity] {
val query = TableQuery[EntitiesTable]
/* line L2: from slick library: ImplicitColumnTypes */
override implicit val mappingId = driver.simple.longColumnType
}
}
End point to execute queries:
val c = new EntityComponent {
lazy val driver = play.api.db.slick.Config.driver
}
db.withSession { implicit session =>
c.Entities.findById(1) foreach println
}
The main question is how to get rid of "implicit val mappingId" overriding in line L2?
I tried to create a class:
abstract class IdImplicits[E<:HasId](implicit val mappingId:BaseColumnType[E#Id])
and inherited it as follows:
object Entities extends IdImplicits[EntitiesTable, Entity]
with HasIdActions[EntitiesTable, Entity] {
val query = TableQuery[EntitiesTable]
//override implicit val mappingId: driver.simple.longColumnType
}
However it seems to me that such approach is redundant.
It would be great if I could hide "implicit val mappingId" inside SlickExtensions.
Here is the link to the same question
UPD:
In my project, I'd like to add HasName, HasValue[V] and some other mixins to construct the following DAOs:
object EntitiesDAO extends HasIdActions
with HasNameActions
with HasValueActions with NameToIdActions with ValueToIdActions {
...
override def nameToId(name:String):Option[E#Id]
override def valueToId(value:E#ValueType):Option[E#Id]
...
}
It leads to the following problems:
1) implicits for BaseColumnTypes, mentioned in my topic, should be taken into consideration for HasId, HasValue mixins
2) If implicits BaseColumnTypes are used as parameters of constructor of abstract classes then these classes can't be mixed in one EntityDAO object (the problem is described here).
3) If one abstract class is used for each variant of EntityDAO, then we get ugly-looking combinations, for example:
abstract class IdValueNameImplicits[E <: HasId with HasValue with HasName]
(implicit val idMapper:BaseColumnType[E#Id],
implicit val valueMapper:BaseColumnType[E#ValueType])
You can't do that because you are inside a trait and E#Id is only defined when you have a concrete implementation of it.
As you already discovered, you have to define your BaseColumnType when your trait is implemented because only then you have a defined type for E#Id.
Another option is not to have a trait but an abstract class where you can have a implicit BaseColumnType passed to the constructor.
I have a small project that does exactly what you are looking for. You can find it here: https://github.com/strongtyped/active-slick
There is also an Activator template.
http://typesafe.com/activator/template/slick-active-record
You can use it as is or as inspiration for your own.
Have fun!

Scala type system - help understanding mismatch on type alias

I'm new to the Scala type system, and I'm trying to explore it via this JAXB Marshalling example. It works if you change the type of the parameter to toString to AnyRef. However, I would like to express via the type system that the parameter to toString must be the same type as the type-parameter to concrete constructor. Is there a way to achieve this?
I don't understand why the error message below seems to indicate that typ = XMLMarshaller[TestObj] instead of just TestObj. In my debugger, typ=TestObj. Any help with this specific question or insight on this piece of code in general is very much appreciated!
error: type mismatch; found : TestObj required: _1.typ where val
_1: XMLMarshaller[TestObj]
val o = new XMLMarshaller[TestObj]().toString(new TestObj("hello","world"))
Here's the code, just paste into REPL:
import javax.xml.bind.{Marshaller, JAXBContext}
import java.io.{ByteArrayInputStream, StringWriter}
import org.jboss.resteasy.plugins.providers.jaxb.json.JettisonMappedContext
import javax.xml.bind.annotation.{XmlRootElement, XmlAccessorType, XmlAccessType}
abstract class XMarshaller {
val context:JAXBContext
type typ <: AnyRef
def toString(obj:typ): String = {
val marshaller:Marshaller = context.createMarshaller()
val sw = new StringWriter
marshaller.marshal(obj, sw)
sw.toString
}
def valueOf(xmlString:String): typ = {
val marshaller = context.createUnmarshaller()
marshaller.unmarshal(new ByteArrayInputStream(xmlString.getBytes())).asInstanceOf[typ]
}
}
class XMLMarshaller[T](implicit mT:Manifest[T]) extends XMarshaller {
val typ = mT.erasure
val context = JAXBContext.newInstance(typ)
}
class JSONMarshaller[T](implicit mT:Manifest[T]) extends XMarshaller {
val typ = mT.erasure
val context = new JettisonMappedContext(typ)
}
#XmlRootElement
#XmlAccessorType(value = XmlAccessType.FIELD)
case class TestObj(x:String, y:String){
def this() {this("","")}
}
object Test {
def main(args: Array[String]) {
val o = new XMLMarshaller[TestObj]().toString(new TestObj("hello","world"))
println(o)
}
}
Because of how Scala's syntax works, a class can have type member and a value
member with the same name, and not create any name conflits (you can always
tell by the context which is meant).
What you have is analogous to:
abstract class FooAbstract {
type Type <: AnyRef
}
class FooConcrete[T<:AnyRef](implicit mt: Manifest[T]) extends FooAbstract {
val Type = mt.erasure
}
where FooConcrete does not override the type member Type. You actually want
class FooConcrete[T<:AnyRef](implicit mt: Manifest[T]) extends FooAbstract {
type Type = T
}
The curious thing is that Scala allows you to fail to override the type, and
leave it completely abstract. I'm not sure if this is intentional or a Scala
bug.