Given:
abstract class A { def show: Unit }
trait T extends A {
abstract override def show: Unit = {
print(" T"); super.show; print(" xT")
}
}
trait U extends A {
abstract override def show: Unit = {
print(" U"); super.show; print(" xU")
}
}
class C extends A {
def show: Unit = print(" C")
}
I can do:
new C with T with U show
But, it "feels" (given Scala's propensity for shortened syntaxes and anonymous stuff in general) like I might be able to instantiate my mixed in class from an anonymous form. Something on the lines of
// doesn't work like this at least:
val a = new { def show { print("Anon")}} with T with U
a show
But I have entirely failed to determine if I'm simply using the wrong syntax, or if this is simply not possible. Can someone tell me how this should be done, or if it definitely is not possible?
I don't think this is possible.
The following two proposals are as close as I can get.
Use Constructor with Mixins
The following solution requires an additional helper class D,
but the end result looks almost as your fictional syntax, except
that you need one additional character for D, and you have to
use round parentheses instead of curly braces:
import scala.language.postfixOps
abstract class A { def show: Unit }
trait T extends A {
abstract override def show: Unit = {
print(" T"); super.show; print(" xT")
}
}
trait U extends A {
abstract override def show: Unit = {
print(" U"); super.show; print(" xU")
}
}
class C extends A {
def show: Unit = print(" C")
}
new C with T with U show
class D(s: => Unit) extends A {
def show = s
}
// that's pretty close, isn't it?
val a = new D(print("hurray!")) with T with U
a show
Just hide the class in a block
If you just don't want to litter the namespace with classes that you use only once, then just enclose the class in a block:
val a = {
class D extends A {
def show = println("NoPollution")
}
new D with T with U
}
a show
What you wanted is to "eliminate the useless variable D" in the above "class-valued compile-time-evaluated-expression", but I don't see how one could do that.
Isn't this what you want?
val a = new T with U {override def show { print("Anon")}}
Syntax is pretty much the same as with declaring a new class, first the extensions/mixins, then the body.
Related
I have an implicit class defined in a class injected in other classes like this
class A {
implicit class B(s: String) {
def b = ???
}
}
class C(a: A) {}
Is there a way to access implicit class B (and in particular its method b) from the class C, without importing it explicitly? (Please note that class A could not be a trait since it also injects some classes.)
Solution 1 (import a._)
Well, yes, as already noted in the comments, from your requirements it is not obvious why you wouldn't just import a._ in the body of C:
class A {
implicit class B(arg: String) {
def b: String = ???
}
}
class C(a: A) {
import a._
{
println("hello".b)
}
}
This one line really doesn't hurt anyone.
If you still don't like it, then the problem might be elsewhere. Thus my second proposal.
Solution 2 (separating typeclass-like A-interface from .b-syntax)
This other solution is less about the reduction of number of imports in your code, and it doesn't even keep class B inside A. But it might address another issue that you maybe just can't quite articulate: it separates the functionality provided by A from the syntax provided by B.
The structure of the following snippet is inspired by the design of the Scala Cats library, that follows a very clear policy with the implicit declarations, always separating the typeclass defintions from the syntax.
The main idea is that:
Implementations of AIntf provide actual functionality
B provides only some additional "pimp-my-library"-style methods
and that we want to keep these two things separate.
Here is how to separate them, thereby also avoiding import a._ inside of C. First, you define the interface that describes the functionality provided by A:
trait AIntf {
def usefulOperationOnStrings(s: String): String
}
Then you can implement it by a few different A`s:
class A extends AIntf {
def usefulOperationOnStrings(s: String): String = "<foo>" + s + "</foo>"
}
class A2 extends AIntf {
def usefulOperationOnStrings(s: String): String = s.toUpperCase
}
Note that the object B has disappeared from A. Instead, it is moved in a separate syntax-package, and renamed to A_Ops. The method b is also renamed to a:
object syntax /* should be package, object only for script */ {
object a {
class A_Ops(wrapped: String, ai: AIntf) {
def a: String = ai.usefulOperationOnStrings(wrapped)
}
implicit def everyStringHasAOps(s: String)(implicit ai: AIntf): A_Ops = {
new A_Ops(s, ai)
}
}
}
This is how you use it:
You say in the imports that you want to refer to interface A_Intf
You say in the imports that you want to use the syntax syntax.a._
You declare the a-argument of C as implicit
Then you can just use "string".a syntax inside C without further imports.
In code:
import myproject.AIntf
import myproject.syntax.a._
class C(implicit val a: AIntf) {
{
println("hello".a)
}
}
Now the implementations of AIntf and the syntax .a become independent. You can inject A2 instead of A. Or you can change the syntax from "str".a to "str".somethingEntirelyDifferent.
The full code snippet:
import scala.language.implicitConversions
object myproject /* should be package, object only for script */ {
trait AIntf {
def usefulOperationOnStrings(s: String): String
}
object syntax /* should be package, object only for script */ {
object a {
class A_Ops(wrapped: String, ai: AIntf) {
def a: String = ai.usefulOperationOnStrings(wrapped)
}
implicit def everyStringHasAOps(s: String)(implicit ai: AIntf): A_Ops = {
new A_Ops(s, ai)
}
}
}
class A extends AIntf {
def usefulOperationOnStrings(s: String): String = "<foo>" + s + "</foo>"
}
class A2 extends AIntf {
def usefulOperationOnStrings(s: String): String = s.toUpperCase
}
}
import myproject.AIntf
import myproject.syntax.a._
class C(implicit val a: AIntf) {
{
println("hello".a)
}
}
val c1 = new C()(new myproject.A)
val c2 = new C()(new myproject.A2)
// prints:
// <foo>hello</foo>
// HELLO
Unfortunately, I have no clue what guice is going to do with an implicit argument, have not tried it yet. It might force you to write
class C #Inject()(val a: AIntf) {
implicit aintf: AIntf = a
...
}
which then becomes longer then the simple import mentioned in the first part.
as noted in comment, just import a._:
class A {
implicit class B(s: String) {
def b: String = "hello "+ s
}
}
class C(a: A){
import a._
val hello = "world".b
}
val c = new C(new A)
c.hello // "hello world"
So I am a bit new to scala.
How does one write scala code to reference a method from case class's companion object in a generic fashion? I have tried a couple of different approaches and can't seem to find one that works.
Below is some sample code that works, but I have to manually build each subclass.
For example:
class One extends Act[LetterA] {
val intro = LetterA.sayhi
}
I would much rather do something like:
class AllOfThem[T <: LettersClass, S <: LettersSingleton] extends Act[T] {
val intro = S.sayhi
}
but I can't seem to find syntax that works or will compile. What is the proper way to do this, or am I looking for something that is not supported in the language? I recognise I am probably a little off on how I am structuring my classes and traits, but I am not sure how to best tackle this desired behaviour.
Additionally, is there a way to something similar to what I have commented out in the method 'actionTwo' in the Act class?
Sample Code listing:
trait LettersSingleton {
def sayhi() : String
}
trait LettersClass {
val id : Int
}
// trait Letters extends LettersClass with LettersSingleton { }
object LetterA extends LettersSingleton {
def sayhi = "Hi I am A"
}
object LetterB extends LettersSingleton {
def sayhi = "Hi I am B"
}
case class LetterA( val id : Int ) extends LettersClass { }
case class LetterB( val id : Int, val name:String ) extends LettersClass { }
abstract class Act[ T <: LettersClass ] {
val intro : String
def actionOne( a : T ) = {
println( a.id + " is my id" )
}
def actionTwo() = {
// println( T.sayhi )
}
}
class One extends Act[LetterA] {
val intro = LetterA.sayhi
}
class Two extends Act[LetterB] {
val intro = LetterB.sayhi
}
So you can't do exactly what you want, but you can get very close with the commonly used typeclass pattern:
//add a type parameter, now you have a typeclass
trait LettersSingleton[T] {
def sayhi() : String
}
//LettersClass stays the same
object Implicits {
//implicit classes/objects have to go inside an object
//create typeclass instances as implicit objects
implicit object LetterASingleton extends LettersSingleton[LetterA] {
def sayhi = "Hi I am A"
}
implicit object LetterBSingleton extends LettersSingleton[LetterB] {
def sayhi = "Hi I am B"
}
}
import Implicits._
//add an implicit parameter to the class
abstract class Act[ T <: LettersClass ](implicit singleton: LettersSingleton[T]) {
def actionTwo() = {
println( singleton.sayhi )
}
}
(new Act[LetterA]).actionTwo() //prints "Hi I am A"
(new Act[LetterB]).actionTwo() //prints "Hi I am B"
So basically what happens is any time you create a new Act[T], the compiler is going to try to fill in the implicit parameter for you by looking for any implicit objects or vals of the correct type in scope. So
val a = new Act[LetterA]
will actually become
val a = new Act[LetterA](LetterASingleton)
You'll notice that the singletons are no longer the companion objects of the case classes, which is fine. You have to define a trait regardless, so it doesn't make much different whether it's the companion object or some other object that implements it.
I'm trying to write a unit test for object A, which uses some methods from another object B. How do I override B's methods?
A.scala
import somePackage.B
object A { // This is to be tested
def fun1(str: String) = {
val str2 = processStr(str) //Say str2 = "sahil"
B.doSomething(str2) // This is to be overridden
}
B.scala
object B {
private def doSomething(str: String) = {
// do something
"abc"
}
}
ATest.scala
class ATest extends FlatSpec {
it "should return sahil instead of abc" in {
// Do something to override B.doSomething
A.fun1("someString")
}
}
This is a design failure at architectural level and a typical XY problem. You should not use singleton without a (really) compelling reason.
Instead for both testability and modularity, consider injecting your dependency explicitly (right now you are declaring the dependency between A and B implicitly through singleton).
class A(b: B) {
def fun1(str: String) = b.doSomething(str)
}
class B {
def doSomething(str: String) = "abc"
}
class ATest extends FlatSpec {
it "" in {
val b = new B { override def doSomething(str: String) = "testing..." }
val a = new A(b)
a.fun1("someString") must beEqual "testing..."
}
}
There is no easy way to do this. Without using DI the only thing that comes to my mind is to overload fun1 with package-private modifier:
package somePackage
import somePackage.B
object A {
def fun1(str: String) = fun1(B.doSomething)
private[somePackage] def fun1(str: String, f: (String) => String) = {
val str2 = processStr(str)
f(str2)
}
}
Then you can pass any mock you would like into fun1
Having read various posts on delayedInit, I was surprised to learn that it's actually called each time by the various subclasses during construction. I wasn't sure I believed this but then I made the test below. Anyhow, my question is that delayedInit sounded like a useful mechanism to drive some kind of final action from an abstract class (for example, perhaps notifying another object of creation complete). And this would make sense, if it were only called once.
But how can any kind of useful construct be made from a function if you risk it being called repeatedly without any other useful information being passed in it's parameters? How could I program it to only fire at the last level of construction, without necessarily knowing how deeply class A has been extended?
object LearnDelayedInit extends App {
class A extends DelayedInit {
def delayedInit(x: => Unit) {
x // call constructor code
println("delayed init called")
}
}
class B extends A {
println("Hello from B")
}
class C extends B {
println("hello from C")
}
val c = new C
}
Output:
Hello from B
delayed init called
hello from C
delayed init called
If you make the hierarchy out of traits and only the leaf type a class you will get the behavior you want:
object LearnDelayedInit extends App {
trait A extends DelayedInit {
def delayedInit(x: => Unit) {
x //call constructor code
println("delayed init called")
}
}
trait B extends A {
println("Hello from B")
}
class C extends B {
println("hello from C")
}
val c = new C
}
Only the initialization code for classes is wrapped and passed to delayedInit, traits have their initialization code run in the constructor as usual.
Here you go.
The future stuff is just for flair.
The basic idea is that the val done is initialized exactly once, in the initializer of C or whatever the bottom class is.
You have read the one question in The One Question FAQ, I suppose.
object Test extends App {
import java.util.concurrent.{ CountDownLatch => Latch }
trait FutureInit {
import concurrent._
import ExecutionContext.Implicits._
private var fs = future(())
def done: Boolean
val latch = new Latch(1)
def delayedInit(x: => Unit) {
fs = fs andThen {
case _ =>
x
if (done) { println("All done!") ; latch.countDown() }
}
}
}
class A extends DelayedInit with FutureInit {
println("Hello from A")
Thread sleep 500L
override val done = true
}
class B extends A {
println("Hello from B")
Thread sleep 500L
override val done = true
}
class C extends B {
println("hello from C")
Thread sleep 500L
override val done = true
}
val c = new C
c.latch.await()
println("Good bye.")
val b = new B
b.latch.await()
println("That's all, folks. Go home.")
}
I'm new to scala macros and I'm using scala 2.10.0-RC3.
I want to write a macro that adds a function to a class. Usage example:
trait MyTrait {
def addF = macro { /*add "def f = 3" to class*/ }
}
class MyClass extends MyTrait {
addF //Adds the "def f" to MyClass
}
object Main {
val t = new MyClass
assert(t.f==3)
}
I need this in the following scenario. My first try didn't use macros but didn't work, because I can't inherit the same trait twice.
trait AddF[T] {
def f(t: T) { /* ...do sthg ... */ }
}
class MyClass extends AddF[Int] with AddF[String]
With the macro solution I could write
class MyClass extends MyTrait {
addF[Int]()
addF[String]()
}
Is there a way to do this with scala macros? Or is there another way to achieve this?
It is currently impossible to add, modify or remove definitions visible outside the macro. I.e. you can create a class or a method local to the expansion (e.g. emit a ClassDef tree as a part of the result returns by your macro), but there's no facility to affect the outside world.
However we plan to experiment with this functionality as roughly sketched in http://scalamacros.org/future.html. Also there's already a solid prototype that can generate new top-level classes. Contact me for details if you would like to take a look.
In case I'm not completely confused, simple overloading should provide the desired behavior? For instance, this would work:
trait MyTrait {
def f(i: Int)
def f(i: String)
}
class MyClass extends MyTrait {
def f(i: Int) {
println(i + " was an Int")
}
def f(s: String) {
println(s + " was a String")
}
}
// this allows:
val c = new MyClass()
c.f("hello")
c.f(42)