Here is a conversation that went down between a polyglot programmer (PP) with a variety of experience and Debbie Downer (DD)
PP: It's really easy to redefine methods in Ruby in any context. In Java you have to write lots of extra code to deal with the problem of static methods or singletons in third party libraries, etc...
DD: Yeah, but dynamic methods are dangerous.
PP: It could be a problem, but in practice it never is. This amazing ability to override the existing behavior has been used in statically typed languages for years now and WE DON'T CARE AND IT'S NOT A PROBLEM! Here are some examples; [N]Hibernate decorates concrete PO*Os at runtime with proxies that afford developers the ability to lazily load relationships and track changes in a unit of work. That's what makes it so easy to use and how it knows how to optimize insert and update statements; and Spring uses proxies for @Transactional classes so that one isn't burdened with writing the same boiler plate DB transaction management code over and over.
DD: Those are examples of popular 3rd party libraries with well defined APIs, I am talking about code that people are working on at my company. That's when overusing dynamically typed languages is dangerous.
PP: Java and C# are not immune to problems because concrete implementations of interfaces could be deferred until runtime and anyone could simply give you a different implementation than you expected, but again that DOESN'T MATTER because what we are trying to achieve here is good old fashioned encapsulation and loose coupling. You shouldn't have to worry about the implementation of an interface that someone else is asking you to interact with.
DD: Yeah, but too much encapsulation is dangerous.That's about the time that I walk away to get coffee.