Using Scala macros, can i make implementer of method call super? - scala

Can Scala macros be used to make implementers of a method in a trait invoke the super method. For instance like this:
trait Super {
//some macro magic here: list = super.list ++ child.list
def list: List[String] = List("ein", "zwei", "DIE")
}
class Sub extends Super {
override def list: List[String] = List("4", "5")
}
object Testy extends App {
println(new Sub().list) //List(ein, zwei, DIE, 4, 5)
}
Update:
See comment from #Sergey below - this is not really doable with macros.

I don't think you need macros in this particular case. In order to enforce some data from a superclass' method to be added to all results of implementing methods in any subclass, the preferred approach would be to use a template method. Make a final def performing the addition of the fixed part and an abstract def declaring the variable part, like so:
trait Super {
protected def additionalList: List[String]
final def list: List[String] = List("ein", "zwei", "DIE") ++ additionalList
}
class Sub extends Super {
protected val additionalList = List("4", "5")
}
object Testy extends App {
println(new Sub().list) // List(ein, zwei, DIE, 4, 5)
}
Update: If, however, you need exactly the behavior as specified in the original question, then you're out of luck, I fear: a macro can only affect what it immediately wraps, e.g. a def macro can only transform what is passed into the method, and an annotation macro can only transform its immediate annottee, be it a class, a field, a method, etc. There's no way for a macro to enforce rules on code which doesn't even know about the macro. So basically you have two options: either make your users call super manually, or write an annotation macro and have your users annotate their subclasses with it. Both of these options are easy to omit, unfortunately.

Related

Is it possible to mock a Scala implicit class?

I can extend my Scala class Foo with additional methods via an implicit class:
trait Foo {
def bar: String
}
object FooExtensions {
object implicits {
implicit class FooOps(foo: Foo) {
def baz: String = "baz"
}
}
}
But can I mock out those methods?
import org.mockito.Mockito
import org.scalatest.WordSpec
import org.scalatest.mockito.MockitoSugar
class MySpec extends WordSpec with MockitoSugar {
"My mock" should {
"handle methods from implicit classes" in {
import FooExtensions.implicits._
val foo = mock[Foo]
Mockito.when(foo.baz).thenReturn("bix") // fails at runtime
}
}
}
This compiles, but fails with
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
Is it possible to mock methods added via implicit classes? Hopefully with Mockito (or mockito-scala) but I'm interested in any approach that works.
Thing about extension methods, is that they are basically a syntactic sugar:
trait Foo
implicit class ExtensionMethods(foo: Foo) {
def bar: String = "bar
}
foo.bar
is equal to
new ExtensionMethods(foo).bar
So mocking:
Mockito.when(foo.bar).thenReturn("bix")
becomes:
Mockito.when(new ExtensionMethods(foo).bar).thenReturn("bix")
I think there is no workaround - perhaps PowerMock could let you change class constructor..., but with normal Mockito it is impossible.
Usually, it is not a problem though. That is because either:
you put into extension methods behavior, that only depends on extended value and passed parameters (and extended method is quite often pure function that doesn't require mocking) - if you want to change something there, you change input,
if behavior should change, you implement it inside a type class, and make extension method use that type class to inject behavior
trait Bar {
def bar: String
}
object Bar {
implicit val defaultBar: Bar = new Bar { def bar = "bar" }
}
implicit class ExtensionMethods(foo: Foo) {
def bar(implicit bar: Bar): String = bar.bar
}
// in test
implicit var overridenBar: Bar = ...
assert(foo.bar === "sth")
On a side note: the more functional you'll get the less you'll need to mock things as everything will depend only on input passed inside, and a cascade of mocks will become just a code smell - too tight coupling, too large interfaces, etc. Problem is that many Java libraries do not even follow SOLID principles, which makes them both hard to use/test with FP as well as bad OOP on its own. I'm telling this in case you feel mocking is the only way to go in your case.
The only way to achieve that is to use implicit conversions rather than implicit classes
This is a hack intended to show how this could be achieved, but I'd urge to take a look at the code and see why you actually need to do this
So, following your example, you could modify the code to look like this
trait Foo {
def bar: String
}
object FooExtensions {
object implicits {
implicit fooToOps(foo: Foo): FooOps = new FooOps(foo)
class FooOps(foo: Foo) {
def baz: String = "baz"
}
}
}
and your test
import org.scalatest.WordSpec
import org.mockito.MockitoSugar
class MySpec extends WordSpec with MockitoSugar {
"My mock" should {
"handle methods from implicit classes" in {
val fooOps = mock[FooOps]
implicit fooToOps(foo: Foo): FooOps = fooOps
val foo = mock[Foo]
when(foo.baz) thenReturn "bix" // works
}
}
}
the other thing to consider is that in your production you need to get an implicit parameter of the shape Foo => FooOps so when you call that method from the test the actual implicit mock is provided...
As I said, you can make it work like this, but I agree with Mateusz that you shouldn't need to

Are parameters of self reference only available in the specific trait?

I would like to build a case class DataObject.
case class DataObject(parameter: Double)
I want to be able to extend this if necessary with the functionality to call a function. For that I want to be able to extend it with a trait DataObjectFunctionable to make it functionable. This functionality should only be assignable to DataObject because it only makes sense there.
trait DataObjectFunctionable {
this: DataObject =>
def unimportantfunction(): Double = parameter + 1
protected val aFunction: AFunction
}
The exact implementation shall be defined later, thus I keep the Function abstract. Since the extra functionality shall only be a trait for DataObject and a DataObject with the functionality would be DataObjectFunctionable, I give DataObjectFunctionable as input type for the function.
trait AFunction {
def value(in: DataObjectFunctionable)
}
Now I am going to define my concrete Function.This is all good and well, until I want to excess the inputs parameters.
object MyFunction extends AFunction {
def value(in: DataObjectFunctionable) = in.parameter + 2
}
Now I am told that in.parameter cannot be resolved. Why is that? this: DataObject => makes sure that DataObject's members are also available inside DataObjectFunctionable (as seen with unimportantfunction). Why is it that though this is the case, I don't have parameter at my disposal in MyFunction? Is it just language design or am I doing something wrong?
What should I do instead? I found that
trait DataObjectFunctionable extends DataObject {
this: DataObject =>
def unimportantfunction(): Double = parameter + 1
protected val aFunction: AFunction
}
solves the issue, but is this really the way to go?
As far as I understand, trait DataObjectFunctionable extends DataObject means "the trait DataObjectFunctionable can only be extended by an DataObject or a subclass of it". However, as far as I understand this: DataObject => means the same... Maybe there is a misunderstanding here that led to my issue.
By the way, this is what I hoped for:
val myObject1 = new DataObject(parameter = 5) extends DataObjectFunctionable {
override protected val aFunction: AFunction = MyFunction
}
val myObject2 = new DataObject(parameter = 5)
myObject1.value // returns 5
myObject2.value // that should not be possible, since myObject2 does not get the functionality. I want this to throw a compiler error
Self-reference is akin to "private inheritance".
If you don't want the inherited parameters to be "private" to the trait, why don't you make it inherit from DataObject rather than self-reference it?
Alternatively, you can "export" the self-referenced parameter from the trait with something like def param = parameter.
Also, a word of caution: don't extend case classes, not even with traits. It is almost always a bad idea.

Object extends Trait, Class extends Trait, both have to implement method

I have the following setup:
trait A
{
def doSomething(): Unit;
}
object B extends A
{
override def doSomething(): Unit =
{
// Implementation
}
}
class B(creator: String) extends A
{
override def doSomething(): Unit =
{
B.doSomething() // Now this is just completely unnecessary, but the compiler of course insists upon implementing the method
}
}
Now you may wonder why I even do this, why I let the class extend the trait as well.
The problem is, that somewhere in the Program there is a Collection of A.
So somewhere:
private val aList: ListBuffer[A] = new ListBuffer[A]
and in there, I also have to put Bs (among other derivates, namely C and D)
So I can't just let the B-class not extend it.
As the implementation is the same for all instances, I want to use an Object.
But there is also a reason I really need this Object. Because there is a class:
abstract class Worker
{
def getAType(): A
def do(): Unit =
{
getAType().doSomething()
}
}
class WorkerA
{
def getAType(): A =
{
return B
}
}
Here the singleton/object of B gets returned. This is needed for the implementation of do() in the Worker.
To summarize:
The object B is needed because of the generic implementation in do() (Worker-Class) and also because doSomething() never changes.
The class B is needed because in the collection of the BaseType A there are different instances of B with different authors.
As both the object and the class have to implement the trait for above reasons I'm in kind of a dilemma here. I couldn't find a satisfying solution that looks neater.
So, my question is (It turns out as a non-native-speaker I should've clarified this more)
Is there any way to let a class extend a trait (or class) and say that any abstract-method implementation should be looked up in the object instead of the class, so that I must only implement "doSomething()" (from the trait) once (in the object)? As I said, the trait fulfills two different tasks here.
One being a BaseType so that the collection can get instances of the class. The other being a contract to ensure the doSomething()-method is there in every object.
So the Object B needs to extend the trait, because a trait is like a Java interface and every (!) Object B (or C, or D) needs to have that method. (So the only option I see -> define an interface/trait and make sure the method is there)
edit: In case anyone wonders. How I really solved the problem: I implemented two traits.
Now for one class (where I need it) I extend both and for the other I only extend one. So I actually never have to implement any method that is not absolutely necessary :)
As I wrote in the comment section, it's really unclear to me what you're asking.
However, looking at your code examples, it seems to me that trait A isn't really required.
You can use the types that already come with the Scala SDK:
object B extends (()=>Unit) {
def apply() { /* implementation */ }
}
Or, as a variant:
object B {
val aType:()=>Unit = {() => /* implementation */ }
}
In the first case, you can access the singleton instance with B, in the second case with B.aType.
In the second case, no explicit declaration of the apply method is needed.
Pick what you like.
The essential message is: You don't need a trait if you just define one simple method.
That's what Scala functions are for.
The list type might look like this:
private val aList:ListBuffer[()=>Unit] = ???
(By the way: Why not declare it as Seq[()=>Unit]? Is it important to the caller that it is a ListBuffer and not some other kind of sequence?)
Your worker might then look like this:
abstract class Worker {
def aType:()=>Unit // no need for the `get` prefix here, or the empty parameter list
def do() {aType()}
}
Note that now the Worker type has become a class that offers a method that invokes a function.
So, there is really no need to have a Worker class.
You can just take the function (aType) directly and invoke it, just so.
If you always want to call the implementation in object B, well - just do that then.
There is no need to wrap the call in instances of other types.
Your example class B just forwards the call to the B object, which is really unnecessary.
There is no need to even create an instance of B.
It does have the private member variable creator, but since it's never used, it will never be accessed in any way.
So, I would recommend to completely remove the class B.
All you need is the type ()=>Unit, which is exactly what you need: A function that takes no parameters and returns nothing.
If you get tired of writing ()=>Unit all the time, you can define a type alias, for example inside the package object.
Here is my recommentation:
type SideEffect = ()=>Unit
Then you can use SideEffect as an alias for ()=>Unit.
That's all I can make of it.
It looks to me that this is probably not what you were looking for.
But maybe this will help you a little bit along the way.
If you want to have a more concrete answer, it would be nice if you would clarify the question.
object B doesn't really have much to do with class B aside from some special rules.
If you wish to reuse that doSomething method you should just reuse the implementation from the object:
class B {
def doSomething() = B.doSomething()
}
If you want to specify object B as a specific instance of class B then you should do the following:
object B extends B("some particular creator") {
...
}
You also do not need override modifiers although they can be handy for compiler checks.
The notion of a companion object extending a trait is useful for defining behavior associated with the class itself (e.g. static methods) as opposed to instances of the class. In other words, it allows your static methods to implement interfaces. Here's an example:
import java.nio.ByteBuffer
// a trait to be implemented by the companion object of a class
// to convey the fixed size of any instance of that class
trait Sized { def size: Int }
// create a buffer based on the size information provided by the
// companion object
def createBuffer(sized: Sized): ByteBuffer = ByteBuffer.allocate(sized.size)
class MyClass(x: Long) {
def writeTo(buffer: ByteBuffer) { buffer.putLong(x) }
}
object MyClass extends Sized {
def size = java.lang.Long.SIZE / java.lang.Byte.SIZE
}
// create a buffer with correct sizing for MyClass whose companion
// object implements Sized. Note that we don't need an instance
// of MyClass to obtain sizing information.
val buf = createBuffer(MyClass)
// write an instance of MyClass to the buffer.
val c = new MyClass(42)
c.writeTo(buf)

How to design immutable model classes when using inheritance

I'm having trouble finding an elegant way of designing a some simple classes to represent HTTP messages in Scala.
Say I have something like this:
abstract class HttpMessage(headers: List[String]) {
def addHeader(header: String) = ???
}
class HttpRequest(path: String, headers: List[String])
extends HttpMessage(headers)
new HttpRequest("/", List("foo")).addHeader("bar")
How can I make the addHeader method return a copy of itself with the new header added? (and keep the current value of path as well)
Thanks,
Rob.
It is annoying but the solution to implement your required pattern is not trivial.
The first point to notice is that if you want to preserve your subclass type, you need to add a type parameter. Without this, you are not able to specify an unknown return type in HttpMessage
abstract class HttpMessage(headers: List[String]) {
type X <: HttpMessage
def addHeader(header: String):X
}
Then you can implement the method in your concrete subclasses where you will have to specify the value of X:
class HttpRequest(path: String, headers: List[String])
extends HttpMessage(headers){
type X = HttpRequest
def addHeader(header: String):HttpRequest = new HttpRequest(path, headers :+header)
}
A better, more scalable solution is to use implicit for the purpose.
trait HeaderAdder[T<:HttpMessage]{
def addHeader(httpMessage:T, header:String):T
}
and now you can define your method on the HttpMessage class like the following:
abstract class HttpMessage(headers: List[String]) {
type X <: HttpMessage
def addHeader(header: String)(implicit headerAdder:HeaderAdder[X]):X = headerAdder.add(this,header) }
}
This latest approach is based on the typeclass concept and scales much better than inheritance. The idea is that you are not forced to have a valid HeaderAdder[T] for every T in your hierarchy, and if you try to call the method on a class for which no implicit is available in scope, you will get a compile time error.
This is great, because it prevents you to have to implement addHeader = sys.error("This is not supported")
for certain classes in the hierarchy when it becomes "dirty" or to refactor it to avoid it becomes "dirty".
The best way to manage implicit is to put them in a trait like the following:
trait HeaderAdders {
implicit val httpRequestHeaderAdder:HeaderAdder[HttpRequest] = new HeaderAdder[HttpRequest] { ... }
implicit val httpRequestHeaderAdder:HeaderAdder[HttpWhat] = new HeaderAdder[HttpWhat] { ... }
}
and then you provide also an object, in case user can't mix it (for example if you have frameworks that investigate through reflection properties of the object, you don't want extra properties to be added to your current instance) (http://www.artima.com/scalazine/articles/selfless_trait_pattern.html)
object HeaderAdders extends HeaderAdders
So for example you can write things such as
// mixing example
class MyTest extends HeaderAdders // who cares about having two extra value in the object
// import example
import HeaderAdders._
class MyDomainClass // implicits are in scope, but not mixed inside MyDomainClass, so reflection from Hiberante will still work correctly
By the way, this design problem is the same of Scala collections, with the only difference that your HttpMessage is TraversableLike. Have a look to this question Calling map on a parallel collection via a reference to an ancestor type

How can I add new methods to a library object?

I've got a class from a library (specifically, com.twitter.finagle.mdns.MDNSResolver). I'd like to extend the class (I want it to return a Future[Set], rather than a Try[Group]).
I know, of course, that I could sub-class it and add my method there. However, I'm trying to learn Scala as I go, and this seems like an opportunity to try something new.
The reason I think this might be possible is the behavior of JavaConverters. The following code:
class Test {
var lst:Buffer[Nothing] = (new java.util.ArrayList()).asScala
}
does not compile, because there is no asScala method on Java's ArrayList. But if I import some new definitions:
class Test {
import collection.JavaConverters._
var lst:Buffer[Nothing] = (new java.util.ArrayList()).asScala
}
then suddenly there is an asScala method. So that looks like the ArrayList class is being extended transparently.
Am I understanding the behavior of JavaConverters correctly? Can I (and should I) duplicate that methodology?
Scala supports something called implicit conversions. Look at the following:
val x: Int = 1
val y: String = x
The second assignment does not work, because String is expected, but Int is found. However, if you add the following into scope (just into scope, can come from anywhere), it works:
implicit def int2String(x: Int): String = "asdf"
Note that the name of the method does not matter.
So what usually is done, is called the pimp-my-library-pattern:
class BetterFoo(x: Foo) {
def coolMethod() = { ... }
}
implicit def foo2Better(x: Foo) = new BetterFoo(x)
That allows you to call coolMethod on Foo. This is used so often, that since Scala 2.10, you can write:
implicit class BetterFoo(x: Foo) {
def coolMethod() = { ... }
}
which does the same thing but is obviously shorter and nicer.
So you can do:
implicit class MyMDNSResolver(x: com.twitter.finagle.mdns.MDNSResolver) = {
def awesomeMethod = { ... }
}
And you'll be able to call awesomeMethod on any MDNSResolver, if MyMDNSResolver is in scope.
This is achieved using implicit conversions; this feature allows you to automatically convert one type to another when a method that's not recognised is called.
The pattern you're describing in particular is referred to as "enrich my library", after an article Martin Odersky wrote in 2006. It's still an okay introduction to what you want to do: http://www.artima.com/weblogs/viewpost.jsp?thread=179766
The way to do this is with an implicit conversion. These can be used to define views, and their use to enrich an existing library is called "pimp my library".
I'm not sure if you need to write a conversion from Try[Group] to Future[Set], or you can write one from Try to Future and another from Group to Set, and have them compose.