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"
Related
I would like to have a class B that inherits from a generic class A that is parametrized by an inner type of B. Specifically, I would like this (minimized example):
class A[T]
class B extends A[T] {
class T
}
Written like this, the compiler does not accept it. Is there any way to specify this inheritance relationship? (Using some different syntax, or some tricks.)
If not, what would be an official reference documenting that this is not possible?
Notes:
Yes, I want T to be an inner class. I do want separate instances of B to have incompatible types T.
This question considers the same situation but does not ask whether/how it is possible, but instead asks for other ways to write the same thing. (At least that's how the answers seem to interpret it.) In any case, that question is ten years old, and Scala may have evolved since.
Clarification: I want B to inherit from A, not from an inner class of A, or have an inner class of B inherit from A. The reason is that I want to use it in the following situation: A is a type class. B is supposed to provide a quick way to easily generate new classes of that type class (with minimal boilerplate). I want to the user of the class to do something like: implicit val X = createBInstance(), and then they will be able to use the type X.T and it will have type class A. The best I managed so far is to support the pattern val X = createBInstance(); implicit val xTypeclass = X.typeclass and use X.T. This means more boilerplate, the possibility to forget something, and it pollutes the namespace more (additional name xTypeclass). (For the very curious: A is MLValue.Converter, B is QuickConverter, and X is Header/RuntimeError/... in my code.)
You can try
class A {
type T
}
class B extends A {
class T
}
val b: B = new B
val t: b.T = new b.T
I made T a type member rather than type parameter.
Here a class overrides a type.
If you want to use T also as a type parameter you can introduce Aux-type
object A {
type Aux[_T] = A { type T = _T }
}
and use type A.Aux[T] as a replacement to your original A[T].
Now you're doing
trait A[X]
class B {
class T
/*implicit*/ object typeclass extends A[T]
}
val b = new B
implicit val b_typeclass: b.typeclass.type = b.typeclass
val b1 = new B
implicit val b1_typeclass: b1.typeclass.type = b1.typeclass
implicitly[A[b.T]]
implicitly[A[b1.T]]
Please notice that making object typeclass implicit is now useless.
Making object typeclass implicit would be useful if you made b, b1 objects rather than values
trait A[X]
class B {
class T
implicit object typeclass extends A[T]
}
object b extends B
object b1 extends B
implicitly[A[b.T]]
implicitly[A[b1.T]]
If you want to make B extend A then as earlier I propose to replace type parameter of A with a type member. A will still be a type class, just type-member type class rather than type-parameter type class
trait A {
type X
}
object A {
type Aux[_X] = A {type X = _X}
}
class B extends A {
type X = T
class T
}
implicit object b extends B
implicit object b1 extends B
implicitly[A.Aux[b.T]]
implicitly[A.Aux[b1.T]]
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
I've found usage of the following in Scala examples, but I can't find proper reference (probably because Google gets confused by new and with that are very common words...):
var someInstance = new Class with SomeTrait
In the basic documentation about traits I couldn't find anything...
Well... its a way to create instances of Anonymous class.
So,
trait A
trait B
class C extends A
val cb = new C with B
// creates an instance of anonymous class 'C with B'
is same as,
trait A
trait B
class C extends A
class D extends C with B
val d = new D
// creates an instance of class 'D'
Now, cb and d both will have same properties.
I know that "union types" are not supported in Scala, but what about intersection types?
In short, I would like a function like this:
def intersect[A,B,C](a: A, b: B): C = ??? // a & b
Or a method :
class A {
def intersect[B, C](b: B): C = ??? // this & b
}
A and B share a common superclass ensuring the validity of the intersect operation, and C would be a type at the intersection ofA or B.
In my use case, A or B represent either variables or constants (of the same type). I want to distinguish, class-wise, a constant from a variable with singleton domain. If I try to intersect a set with a value, I return the value (or return the empty set/throw an exception if the value is not in the set).
Here is an example of expected output:
trait IntExpression {
// Correct signature to be determined
def intersect [A <: IntExpression, B <: A & this.type] (that: A): B
}
case class IntVariable(domain: Seq[Int]) extends IntExpression
case class IntConstant(value: Int) extends IntExpression
val a = IntVariable(1,2,3)
val b = IntVariable(2,3,4)
val c = IntConstant(2)
And then:
a intersect b == b intersect a == IntVariable(2,3)
a intersect c == c intersect a == IntConstant(2)
As ziggystar is correctly stated above: A & B is A with B in Scala.
Regarding the fact you want to create your adjoint types C in runtime, you must want to create this type in runtime, based on the types you got in A and B.
Solution for this, or at least a clue, you may find at How to mix-in a trait to instance?.
However, what you want at your use-case is a case of the http://en.wikipedia.org/wiki/Dependent_type. In spite of the fact that dependent types are not supported in Scala, you may always try Agda ;)
I use ++ as implementation because it's there. And intersect on Set doesn't work because Set is invariant. If this doesn't make sense, ignore it.
def intersect[C, A <: C, B <: C](as: Seq[A], bs: Seq[B]): Seq[C] = as ++ bs
Suppose that I have:
trait A
class B extends A
compiled into class files.
Later I load those using reflection:
val a = Class forName "A"
val b = Class forName "B"
Could anyone tell me how to check whether b is the subtype of a?
Use the isAssignableFrom method in Class:
a isAssignableFrom b
This returns true if b is a subclass/subinterface of a or b == a.
You can just call the getInterfaces method on b and iterate through the array to see if any of them equals a.