Because although the compiler could deduce that the meow()
call would succeed in this case, it can't do so in every conceivable program, and it's much better to have a simple, easy-to-remember policy of "no type inference" than "I'm going to try some type inference for ya, but I'm warnin' you, I'm not gonna find all the demonstrably legal calls you might expect, so no guarantees."
Therefore, if you're going to call meow()
anyway, there is no point whatsoever in declaring something as Animal
. Just go ahead and admit that it's a Cat
. Interfaces are a useful construct, but they can earn their pay only if you're willing to let them do their abstraction thing, and forget about the exact species.
In general, it rarely makes any sense to declare something as an abstract supertype when you then immediately assign it to a constructor call, i.e. a concrete type. But imagine you had a DogFactory
, a CatFactory
and a BirdFactory
, all of which implement a common PetFactory
interface. The PetFactory
would contain a method Animal getPet()
, and each concrete factory would do something like return new Cat()
. The concrete type is needed to actually construct an object; the interface is needed so that different providers can all satisfy the same interface, which simplifies weaving together the application at a higher level.