1

Coming from a non-Java background to Scala has brought me a wide range of difficulties including this one.

scala> class A
defined class A

scala> class B extends A      
defined class B

scala> val a = new A
a: A = A@2e893a4a

scala> val b = new B
b: B = B@3a47c130

scala> a.asInstanceOf[B]
java.lang.ClassCastException: A cannot be cast to B
...

scala> b.asInstanceOf[A]
res1: A = B@3a47c130

I understand that ClassCastException is thrown because at runtime, a doesn't seem like a B but in fact, it is (as far as I understand). What's going on here? Any workarounds? Thanks.

Edit: how does the JVM understand that a cannot be casted to B? Does it perform some shallow comparison between a.getClass and B?

ps. I'm trying to add a private variable to a library class, and override one of the class methods that accepts a class defined in the library as argument (the class I'm trying to add the field to).

parsa
  • 2,628
  • 3
  • 34
  • 44
  • You can just extend the library class and add the private variable in the extended class and use that class instead? Functions and Methods overide each other in Scala fyi. – mythicalprogrammer Jul 10 '11 at 07:33
  • I'm doing as you said, I extend and add the variable. But a factory class from the library with a method that I need to override, only accepts the old class as an argument. – parsa Jul 10 '11 at 07:38
  • @parsa Compare with this: `val m: A = new B(); m.asInstanceOf[B]`. Hopefully that will make some sense. –  Jul 10 '11 at 07:38
  • Replacing `A` with something like `Animal` and `B` with something like `Dog` makes the question self-explanatory. Every dog is an animal, but not every animal is a dog. – agilesteel Jul 10 '11 at 09:53

2 Answers2

6

It's a hierarchy that goes down. Class A is a super class and B extends from it so it's more specific. You cannot go up the hierarchy in generalization. It's a design choice and relates to subtyping.

Is there any language where you can go up the hierarchy? Cause it seems like you're implying that there is such a language.

mythicalprogrammer
  • 4,647
  • 6
  • 35
  • 42
4

You cant cast A into B, only the other way around, because B is more specific than A.

nfechner
  • 17,295
  • 7
  • 45
  • 64
  • Yes by definition A is a Car and B is a BMW, but with no additional fields or methods, what's prohibiting a to be seen as an B? (Or is it solely there to prevent bad software design?) – parsa Jul 10 '11 at 07:09
  • 2
    @parsa The cast is a *run-time* operation. The type of the *object* is A -- not B in this case -- and thus, *kaboom*! If an *object* of type B hiding in a *variable* of A, then it'd be okay. It's like trying to cast Mammal (A) to a Pig (B). A Pig can Oink, but a Mammal object is more general: it can't Oink :( A Pig is, however, perfectly fine if it's treated like a Mammal. –  Jul 10 '11 at 07:33