It looks like you are confusing overloading and overriding. Remember the main rules:
OVERRIDING - Must have same argument list and return type (or covariant return)
OVERLOADING - Reusing a method name but with different arguments which may have different return types if argument lists are also different
So now that we've established that, let's take another look at your first example:
What do you think that is? It's on OVERLOAD, same name and return type BUT different parameters.
So, in this case you are calling eat() twice, once with an Animal and once with a Horse BUT they are BOTH an Animal Reference (the stuff on the left of the assignment) and the rule for overloading is the the reference type determines what gets called... so if you actually try to run your code you'll see that it prints "Animal is eating!!" TWICE!! where did you get your result from?
Now the second example is an OVERRIDE because you define the eat() method in Animal and then Horse OVERRIDES this method (same arguments and return type) and the rules of overriding are determined by the Object type (the right side of the assignment) so h.eat() will print "Horse is eating" BUT eat(string) is an OVERLOAD and it is determined by the reference type, which in your case is Animal... and since Animal doesn't have that overload the compiler will complain. If you change: