For the first one...understanding the difference between declaring the animal as an instance of its supertype....
The main advantage comes in being able to treat all cats and dogs the same, and not having to know which one you're dealing with. Let's expand the example a bit.
So now we have an Animal that knows how to speak, a Cat that IS-A Animal, and also knows how to purr, and a Dog that IS-A Animal and also knows how to walk.
If we write the following, it will fail to compile.
Specifically, cat.purr() and dog.walk() will not compile. Yes, the Cat is a Cat object, but because it's been declared as an Animal, that's all the compiler knows about.
If we were to comment out the purr() and walk() lines, the Cat and Dog would print the Cat and Dog-specific values; meow and woof respectively, not the "abstract speak" from Animal.
So declaring an object as its superclass or interface can restrict what you are able to do with it. Where is the value in this? Well, it's all about generic handling of code. If you need to know that a Cat can purr(), then declare it as a Cat. If all you need to know is that a Cat IS-A Animal, declare it as an Animal.
For a variable that is declared and used directly, this may not seem too useful. However, whenever you want to handle multiple types of Animals at a time without caring what exact type of Animal they are, it becomes a nice to have. Let's look at the following:
So the compiler knows that the list contains Animals only. It has no real idea whether I put Cats, Dogs, Fishes, Butterflies, or any other Animals in that list. What it does know is that the list contains Animals, and that all Animals can speak.
To give a concrete example of how this type of generic handling is useful in the Java libraries, consider networking access:
The object "s" points to an "InputStream" in the same way as the example "cat" points to an "Animal". But you don't need to know about the exact type of s to be able to use it. It's all about the generic handling. Hopefully this explains it a bit more
For interfaces, why wouldn't you define a reference type as an interface? Interfaces do not define what the class is, rather what it can-do. So if you're handling code from the point of view of can-do rather than is-a, why not use an interface as a reference type? Perhaps a more concrete reason to use interfaces is if we decided a Boat class could also speak(). A Boat is obviously not-an Animal, but it can-do the same thing as a Cat. It's a different way of thinking about the code.
Let's change the example up a bit to suit this new world-view. In this example, you can treat a Cat as both an Animal and a Speaker. It's not true multiple inheritance, but it looks like it..... If it were true multiple inheritance, Speaker would be able to define how-to speak rather than just defining a class that can.
There is no difference when declaring a reference variable between a class and an interface, other than the obvious you can't directly instantiate an instance of an interface. If you're being handed a type by some other code and don't have the documentation at hand to tell you, you can't tell whether that type is an interface or a class.
Hopefully the examples help. And welcome to the Ranch!