The two doSomething() methods take different kinds of arguments -- they have different signatures -- so they're not polymorphic, they're overloads. The compiler chooses one at compile time based on the argument list and reference type.
If you change MySuperclass.doSomething() to accept a String argument, you'll see the polymorphic behavior you're expecting!
Got that. (That's why I added in the doSomethingElse() method.) And you're right, this isn't truly a polymorphism question.
But why would the compiler choose MySuperclass.doSomething()? I would expect that because the underlying object is actually an instance of MySubclass, the called method would be MySubclass.doSomething(). On top of that, the call in main() has a String argument, which would match MySubclass.doSomething(String) method more specifically than MySuperclass.doSomething(Object).
I'm sure I'm thinking about this incorrectly...but I still don't see it.
Got it; thanks! That explains the previous example, and it also explains why
MySubclass: doing something with an object MySubclass: doing something else
. The doSomething(Object) method is chosen at compile time because the reference is to a MySuperclass, but at run time the decision is made to use the subclass's doSomething(Object). Nasty...but now understandable.