Scala macro to generate a class from a trait - scala

I'm looking for a way to generate a class from a trait with all the methods implemented (throwing NotImplementedErrors). Having such class in place, I would be able to sub-class it to provide implementations for the methods I do need.
I consider this approach as a replacement for a mocking framework.
How to do that in scala-meta or scala-reflect?

Related

How to programmatically generate an abstract Scala class extending an annotated trait?

Given an annotated trait, how should I go about generating an abstract class which implements the trait?
So, given the following user trait...
#Neuron
trait SomeTrait {
// ...
}
... in my library I want to insert something like the following next to it:
abstract class SomeTraitImpl extends SomeTrait
Note that I know nothing about the given trait except it's annotated with #Neuron.
I've tried to do this with ASM, implementing the concept explained in the answer to the question Using Scala traits with implemented methods in Java, but this concept scratches only the surface of what the Scala compiler emits as byte code. Even if I succeeded to master all possible combinations of var, val, lazy val, abstract override etc the odds are high that it will break with the next release of the Scala compiler.
So it looks like I should write a compile time macro instead. However, I am scratching my head over the documentation for Scala macros, so I wonder if anyone could draft something which gets me started? Any hint is appreciated, please!
The correct approach to do this is to make #Neuron a macro annotation (using the Macro Paradise compiler plugin) and implement the macro to do the code transformation. The resulting code is now part of Neuron DI, a framework for dependency injection which I wrote.

When should I use a regular class in Scala?

It seems to me that I can make just about anything using object, trait, abstract class and in rare occasions, case class. Most of this is in the form object extends trait. So, I'm wondering, when should I, if ever, use a plain, standard class?
This is not a right place to ask this question
Looks like you are new Scala
Class is a specification for something(some entity) you want to model . It contains behavior and state
There is only one way to declare so called regular class using keyword class
Both trait and abstract class are used for inheritance.
trait is used for inheritance (generally to put common behavior in there). trait is akin to interface in Java. multiple inheritance possible with traits but not abstract class.
A class can extends one class or abstract class but can mixin any number of traits. Traits can have behavior and state.
case class is a nothing but a class but compiler produces some boilerplate code for us to make things easy and look good.
object is used when you want to declare some class but you want to have single instance of the class in the JVM (remember singleton pattern).
If an object performs stateful computations on its members i.e. its members are declared with vars;
Or, even if its member are only declared with vals but those vals store mutable data structures which can be edited in place, then it should be an ordinary (mutable) class akin to a Java mutable object.
The idiomatic way of using Case classes in Scala is as immutable types i.e. all the constructor arguments are vals. We could use vars but then we lose the advantages of case classes like equality comparisons will break over time.
Some advise from Programming in Scala by Odersky et al on deciding between using traits, abstract classes and concrete classes:
If the behavior will not be reused, then make it a concrete class. It is not reusable behavior after all.
If it might be reused in multiple, unrelated classes, make it a trait.
Only traits can be mixed into different parts of the class hierarchy.
If you want to inherit from it in Java code, use an abstract class.
Since traits with code do not have a close Java analog, it tends to be
awkward to inherit from a trait in a Java class. Inheriting from a
Scala class, meanwhile, is exactly like inheriting from a Java class.
As one exception, a Scala trait with only abstract members translates
directly to a Java interface, so you should feel free to define such
traits even if you expect Java code to inherit from it. See Chapter 29
for more information on working with Java and Scala together.
If you plan to distribute it in compiled form, and you expect outside
groups to write classes inheriting from it, you might lean towards
using an abstract class. The issue is that when a trait gains or loses
a member, any classes that inherit from it must be recompiled, even if
they have not changed. If outside clients will only call into the
behavior, instead of inheriting from it, then using a trait is fine.
If efficiency is very important, lean towards using a class. Most Java
runtimes make a virtual method invocation of a class member a faster
operation than an interface method invocation. Traits get compiled to
interfaces and therefore may pay a slight performance overhead.
However, you should make this choice only if you know that the trait
in question constitutes a performance bottleneck and have evidence
that using a class instead actually solves the problem.
If you still do not know, after considering the above, then start by
making it as a trait. You can always
change it later, and in general using a trait keeps more options open.

Dependency injection and Scala's Traits

Do any of the Scala dependency injection allow to inject mixins?
As an example, consider the following traits:
trait MyService extends TraitA with TraitB
Here, TraitA and TraitB are completely abstract traits (i.e. interfaces). In other words, in order to have a concrete implementation of MyService, I need to mix in concrete implementations of TraitA, TraitB respectively.
In pseudo-code, I want to create a concrete module like so:
bind TraitA to TraitALike
bind TraitB to TraitBLike
concreteModule = resolve MyService
Where TraitALike, TraitBLikeare concrete implementations of the abstract traits.
concrete module should now be an instance of MyService extends TraitALike with TraitBLike.
Do any dependency injection frameworks allow for injected mixins in this fashion in Scala?
From all I know there is no such a framework at the moment.
You request is very specific and you would need a some kinda non-trivial cogen to get it working (especially in case you want to do it in runtime).
Though there is no any kind of fundamental problem preventing us from implementing this. For example, DIStage (disclaimer: I'm the author) complements traits (both in runtime and compiletime) allowing you not to write corresponding classes. You may look at the implementation here.
So in fact you just need to intercept calls to trait's methods and forward them to corresponding implementations, this may be done with cglib or javassist, or you may generate relevant dispatchers with a macro.
We may implement this but what's your motivation behind?

What does it mean when object extends class with no implementation

object PostgresDriver extends PostgresDriver
I see this in slick with no implementation whatsoever. I am wonder does that just automatically create a singleton class?
This is pretty standard practice, defining a trait to represent the abstraction and then providing a standard implementation of that trait as an object. If you just do it as the object you don't have an abstraction to refer to it as and stuff like that can make mocking and testing difficult at the least

How to determine to use trait to 'with' or class to 'inject'?

I'm puzzled to choose a trait or class when writing scala code.
At first, I have a controller which with several traits:
class MyController extends Controller
with TransactionSupport
with JsonConverterSupport
with LoggerSupport
In these traits, I defined some methods and fields which can be used in MyController directly.
But my friend says: when you extends or with a trait, it should be a that trait.
Look at the MyController, it is a Controller, but it isn't a TransactionSupport, not a JsonConverterSupport, not a LoggerSupport, so it should not with them.
So the code becomes:
class MyController(tranSupport: TransactionSupport,
jsonConverter: JsonConverterSupport,
loggerSupport: LoggerSupport) extends Controller
But I don't feel good about this code, it just seems strange.
I see traits used heavily in scala code, when should I use it or use classes to inject?
I'll refer you to Interfaces should be Adjectives. Though some traits may play the part of a class (and, therefore, be nouns and respect the "is-a" relationship), when used as mixins they'll tend to play the part of interfaces.
As an "adjective", the trait will add a qualifying property to whatever they are extending. For example, they may be Comparable or Serializable.
It can be a bit hard to find an adjective to fit -- what adjective would you use for LoggerSupport? -- so don't feel overly constrained by that. Just be aware that it is completely wrong to thing of traits as necessarily an "is-a" relationship.
I would try to avoid using traits to replace "has-a" relationships, though.
My opinion is that it doesn't have to be it. Mixing-in is a different concept than inheritance. Even though syntactically it is the same, it doesn't mean the same. Typical use case for mixing-in is logging just like you wrote. It doesn't mean that if your service class mixes-in a Logging trait that it is a logger. It's just a yet another way how to compose functionality into working objects.
Odersky proposes that if you are not sure and you can, use traits because they are more flexible. You can change trait to class in the future if you need.
Sometime when I feel that mixing-in trait doesn't look good, I use module pattern like this:
trait JsonConverterModule {
protected def jsonConverter: JsonConverter
protected trait JsonConverter {
def convert(in: Json): Json
}
}
class MyController extends Controller with JsonConverterModule {
private doSmth = jsonConverter.convert(...)
}
MyController in this case looks more like a Controller, and all Json-related stuff is hidden from MyController 'client'
Your first example with traits is the "cake pattern" and your second example is "constructor injection". Both are perfectly valid ways to do dependency injection in Scala. The cake pattern is powerful, you can inject type members, the different traits can easily talk to each other (we don't have to create separate objects and pass them to each other object, often requiring setter injection rather than simple constructor injection), etc. However, the type has to be realized at compile-time, and a separate class must be realized for every combination of traits. Constructor injection lets you build your object at run-time and scales better for a large number of combinations.