I am new to scala. I try to debug a scala project by idea, So I need to set a conditional breakpoint. However, I found a situation that two subclasses inherits the same trait "Handle", so the two subclasses can be used to as input to a function judge. But, class B has a value name, class C does not have this variable. I want to know, how to judge the input of function "final" has variable "name".
trait Handle {
}
abstract class F {
val name: String
}
class B extends F with Handle {
val name = "..."
}
class C extends Handle {
val h = "..."
}
def final(h:Handle) = {...}
Since Handle is not sealed you cannot enumerate a finite list of all possible implementations. At best you could:
def final(h: Handle) = h match {
case b: B => // h is B, so from now we can access B's method with b
case c: C => // h is C, so from now we can access C's method with c
case _ => // h is some other implementation of Handle
}
If Handle was sealed you could do:
def final(h: Handle) = h match {
case b: B => // h is B, so from now we can access B's method with b
case c: C => // h is C, so from now we can access C's method with c
// compiler can prove that no other implementation than these two is
// possible, so you don't have to consider it with a wildcard match
}
Once you match h against something you have detailed knowledge what you can do with it.
Related
I am using parfait pattern like the following:
trait A {
def a: Future[String]
}
class B {
this: A =>
def get: Future[String] = a
}
I would like to create a mocking version of A so I can control the result of def a using Mockito when testing B, is there a way to do that?
While testing a class X which uses an instance of class Y, we generally provide a mocked instance of class Y.
Here, Your B is not using any instance of A, it expects (forces) that anything extending B also extends A.
Also, you will notice that your class B is kind of incomplete as it is. if you choose to create an instance of B,
val b = new B
// <console>:13: error: class B cannot be instantiated because it does not conform to its self-type B with A
// val b = new B
So. basically whenever you are creating an instance of B you have to also provide an implementation of A.
scala> val b = new B with A { def a = Future.successful("well") }
// b: B with A = $anon$1#11ad095c
Notice, how we are free to provided any implementation of A, whenever we are creating any instance of B.
You can provide whatever you require for your test cases this way.
So,
trait AWithMockedBehaviour1 extends A {
def a = Future.successful("mocked_1")
}
val b = new B with AWithMockedBehaviour1
Scenario is as follows :
Main class reads inputs values (e.g. A, B, C, D) from a LIST iteratively.
Another class contains implementation of separate methods to handle these input values accordingly.
E.g. Method A can be called only if input value is A, method B can be called only if input value is B.
The good part is that all these methods accept exactly same parameter and its types.
e.g. A, B, C, are all of same type.
Is there any way to handle this in Scala?
We can use ENUM and case logic but looking for a better way to do this?
E. G. Scala reflection API or using case classes.
From your question, it's not at all obvious why you would want to use dynamic invocation or reflection.
If all values A, ..., D belong to a common type Foo, then it probably won't get much easier than with case-classes:
sealed trait Foo
case class A(a1: Int, a2: String) extends Foo
case class B(b: Double) extends Foo
case class C(c: String) extends Foo
case object D extends Foo
Every time you want to transform A, ..., D to some other result type R, you can simply write a match-case, and handle the different cases there. If you use it so often that it is still too verbose, you can introduce an eliminator of the type Foo, which accepts bunch of functions, and hides the pattern matching inside:
object Foo {
def elim[R](
aElim: (Int, String) => R,
bElim: Double => R,
cElim: String => R,
dElim: R
)(f: Foo): R = f match {
case A(a1, a2) => aElim(a1, a2)
case B(b) => bElim(b)
case C(s) => cElim(s)
case D => dElim
}
}
In this way, you can trade the naming of the cases in match-case for a shorter syntax, e.g. you could construct an eliminator like this:
val fooToString = Foo.elim(_ + _, "" + _, identity, "D") _
or apply it to a list of As ... Ds directly:
List(A(42, "foo"), B(3.1415d), C("bar"), D).
map(Foo.elim(_ + _, "" + _, identity, "D")).
foreach(println)
This would output
42foo
3.1415
bar
D
If this isn't worth it, just use case classes with usual pattern matching.
I have four traits A, B, C and D in the typical diamond problem hierarchy.
I have implemented a method calculate in trait A which checks the instance of callerObject, performs some calculation and returns trait A type object. calculate method is successfully able to check the instanceType of callerObject when callerObject belongs to trait B or C but doesn't work for object of trait D and I get the following class cast exception:
java.lang.ClassCastException: packageName.B$$anon$1 cannot be cast to packageName.D
Can you please suggest way forward, how can I check the Type of the object from trait D in method of trait A.
PS: I am new to Scala.
With pattern matching the order of the case statements matters. Make sure that the most specific class is always matched at the top. For example if B extends A and C extends B, it means that objects of C will always match anything that looks for either B or A, etc.
Here is a toy example that can better explain the solution:
sealed trait A {
def calculate(i: A) = i match {
case _:D => "d" // Make sure the D is checked first!
case _:B => "b"
case _:C => "c"
// If you want to match for A make sure it is added last
}
}
trait B extends A
trait C extends A
trait D extends B with C
Here is an example in the REPL:
val b = new B{}
val c = new C{}
val d = new D{}
b.calculate(b)
res> "b"
b.calculate(c)
res> "c"
b.calculate(d)
res> "d"
Say I have two classes with the same identifier for a parameterized type
trait A {
type O
def f(a: Int, os: Seq[O]): Int
}
trait B {
type O
def g(a: Int, o: O): Int = { h1(o) + h2(a) }
def h1(o: O): Int
def h2(a: Int): Int = {a/2}
}
I would like to create a child class that will "marry" the two
trait C extends A with B {
def f(a: Int, os: Seq[O]): Int = {
os.map{ o => g(a, o) }.sum
}
}
Finally, I create an implementation for C
class D extends C {
type O = Int
def h1(o: O): Int = {5 * o}
}
At writing of C I don't yet know what type O is -- however, I'd like to constrain A.O == B.O such that it "makes sense" to use B.g in an implementation of A.f. I tried implementing this and it surprisingly seemed like Scala assumed there was only ever one type O
val d = new D
println(d.f(1, Seq(1,2,3)))
To me this seems incorrect -- why should A.O and B.O agree?
EDIT
I'd also like to note that If you were to instead put constraints on O like so,
case class Z()
case class Z1() extends Z
case class Z2() extends Z1
trait A {
type O <: Z
}
trait B {
type O >: Z2
}
class D extends C {
type O = Z1
Compilation will fail. However, if you put this instead,
trait A {
type O <: Z
}
trait B {
type O <: Z1
}
class D extends C {
type O = Z2
Compilation succeeds and everything runs fine.
I think Scala always "marries" the members -- both type and value members -- of traits when both are mixed in:
trait A { type T = Int }
trait B { type T = String }
object C extends A with B
gives
overriding type T in trait A, which equals Int;
type T in trait B, which equals String needs `override' modifier
(it's how Scala deals with the multiple inheritance issue -- no matter how many times an identifier is mixed in, it only exists once).
You second example fails because Scala needs a bit of help in establishing the type bounds in C. I suppose maybe it should be smart enough to figure it out on its own, but someone more versed in type theory would have to explain why or why not. This definition for C should work:
trait C extends A with B {
type O >: Z2 <: Z // restrict O's type so it's valid for both A and B
}
Scala's handling of abstract types is similar to its handling of abstract methods. Methods of the same name (and signature) that are pulled in from multiple traits are overridden together. Take the classic counter-example, derived from an example given in Ye Olde C++ Programming Language.
trait Cowboy {
/** Shoot something */
def draw
}
trait Window {
/** Draw something */
def draw
}
class CowboyWindow {
/** Probably best to draw something on the screen, then shoot it */
def draw {
// ...
}
}
In the same way that it assumes that there's only one type O in your code, it assumes there's only one method draw in this code. In this instance, this assumption is problematic, since you could end up shooting yourself in the foot.
As you discovered in your example, usually this assumption works out for the best (think about multiple interfaces declaring a close() method). But if this assumption is problematic for some class, as it is for CowboyWindow, you can replace inheritance with composition to work around it.
Working through these posts had me thinking I understood self-types, at least somewhat.
So I created an example which failed as expected:
scala> trait A { val v = "a" }
defined trait A
scala> trait B { this :A => ; var v = "" ; this.v = "b" }
<console>:6: error: reassignment to val
trait B { this :A => ; var v = "" ; this.v = "b" }
^
The self-type's "this" shadows B's "this" -- it looks weird, but makes sense.
It would seem wise, then, to give the self-type a different name. I did this and was rather surprised:
scala> trait C { a :A => ; var v = "" ; this.v = "c" }
<console>:6: error: reassignment to val
trait C { a :A => ; var v = "" ; this.v = "c" }
^
It's still shadowed???
Changing the name of the 'local' variable let things compile, which makes sense:
scala> trait D { a :A => ; var w = "" ; this.w = a.v }
defined trait D
(And the self-type name can optionally be used to clarify which "v" to use.)
Okay. Which means that the following should fail?
scala> trait E { this :A => ; var w = "" ; this.w = this.v }
defined trait E
Huh? Which this is this? :-(
So... is there a point to naming self-types? "this" seems to end up shadowed regardless.
Or is this an edge-case of scoping rules, where the self-type's "this" takes precedence over the trait's "this" -- and one should just avoid using the same names for things in related traits?
Your problem is not the name of the self type (in all your examples both this and the alternate self-type name refer to the very same thing and have the same type, namely ‘the greatest lower bound of B and A’ [§5.1, Scala Language Spec]) but that you try to define a field with the same name again without explicitly overriding it.
Look at the simpler example:
trait A { val v = "a" }
trait B { this: A =>
var v = "b"
}
new A with B {} // does not compile
<console>:9: error: overriding value v in trait A$class of type java.lang.String;
variable v in trait B$class of type java.lang.String needs `override' modifier
new A with B {}
So, even though, you don’t get an error in defining B, you’re simply not able to use it anyway.
This would work
trait A { val v = "a" }
trait B { this:A => override val v = "b" }
new A with B {}
Here, you are explicitly overriding A’s v in B. (Note that new B with A {} would fail because B needs to come last.) Also, it has to be a val because in most cases you cannot really override vars and you cannot override something else using a var.
Generally, you should not be concerned about the name of the self-type in these simple cases. As long as you do not create another trait or class inside B, both this and whatever you’d call your self-type variable will point to the same thing. There’ll be no shadowing. If you had a new trait inside B, and you needed to refer to the instance of B inside that trait, you’d need another name for your self-type.
Consider this
trait B { this =>
val v = "b"
trait C {
val v = "c"
println(this.v)
}
new C {}
}
new B {}
// prints c
vs this:
trait B { self =>
val v = "b"
trait C {
val v = "c"
println(this.v) // prints c
println(self.v) // prints b
}
new C {}
}
new B {}
(Without any further type annotation, you could leave out all of the this in this example.)
The self-type is not shadowing this. It IS the type of this. (Actually the self-type is the intersection: in trait A { self: B => ...} the type of this is A with B.) You can supply a name when giving the self type as a convenience to disambiguate multiple thises, but as you never have more than one this in any of your code snippets, it's irrelevant.
[...] where the self-type's "this" takes precedence over the trait's "this"
You have this same idea several places, that there is more than one this. There isn't. There is only this. You don't get another this until you declare another template.
trait A {
self1 =>
trait B {
self2 =>
// Here unqualified this refers to B and not A, so "self1" is useful.
// ...but not necessary, because A.this.xxx does the same thing.
}
}