Consider the following hierarchy:
class C1
class C2 extends C1
class C3 extends C2
class C4 extends C3
I want to write a function that just accepts types C2
and C3
. For that I thought of the following:
def f [C >: C3 <: C2](c :C) = 0
I'd expect the following behaviour
f(new C1) //doesn't compile, ok
f(new C2) //compiles, ok
f(new C3) //compiles, ok
f(new C4) // !!! Compiles, and it shouldn't
The problem is when calling it with C4
, which I don't want to allow, but the compiler accepts. I understand that C4 <: C2
is correct and that C4
can be seen as a C3
. But when specifying the bound [C >: C3 <: C2]
, I would expect the compiler to find a C
that respects both bounds at the same time, not one by one.
Question is : Is there any way to achieve what I want, and if not, is the compiler trying to avoid some inconsistency with this?
Edit: from the answers I realized that my presumption is wrong. C4
always fulfills C >: C3
, so both bounds are indeed respected. The way to go for my use case is C3 <:< C
.
Statically, yes. It's pretty simple to impose this constraint:
def f[C <: C2](c: C)(implicit ev: C3 <:< C) = 0
f(new C4)
wouldn't compile now.
The problem is, it's probably not possible to prohibit the following behaviour at compile time:
val c: C3 = new C4
f(c)
Here variable c
has static type C3
, which passes any kind of typechecking by compiler, but it is actually a C4
at runtime.
At runtime you can of course check the type using reflection or polymorphism and throw errors or return Failure(...)
or None
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With