Learn thing -> abuse use of thing -> actually start to understand thing (hopefully) -> use thing appropriately -> learn new thing -> ...
My thoughts are interfaces are starting to change...mature? I think the .NET convention of an 'I' (ex: IEncryptionAlgorithm) prefixed defeats part of the point. I think that encourages us to see it as an interface code construct and not the required object description that your module/class/method wants. Perhaps Java's '*able' (ex: Runnable) is a better one. I hope that makes sense but I'm starting to think a lot of developers have focused on "this is a class" or "this is an interface" when both are actually an object description and when you take that in as a parameter you are saying I require these members. When I start thinking that way I start thinking that class methods should be virtual by default and that in general we probably don't use interfaces correctly (hell a lot of people don't use them at all I'm sure). Just having a class by default have virtual methods means we could mock a class the same as an interface. This does mean that you couldn't rely on a class's implementation at runtime but you shouldn't be programming against the implementation anyway.
Of course then I think about how it's easier to reason about a class if it's sealed up nicely. It's also easier to reason about code interactions if types are explicit, but then again it's easier to write tightly coupled code if types are explicit. Perhaps since class members are by default non-virtual, proper use of things like TypeMock should be encouraged.
My biggest objection is if it allows you to open up the class and mock out a hidden internal dependency. If you needed to mock an internal dependency to properly test a class then perhaps it should be an explicit dependency instead (pass in through a parameter).
Beyond mocking, interfaces should be encouraged as well since they are what provide real modular and reusable code. Type hierarchies only project shared/related implementation reuse which I don't think helps an application on a whole, just a piece of a subsystem or layer. They are best at describing related types, perhaps that's all they should be used for and not for passing around or interacting between subsystems.
I think this has been influenced by my interest in dynamic and message passing style languages. I also think this is just my understanding of object-oriented design hopefully increasing (you never can judge your own aptitude). So I'm thinking I'm leaving behind a phase of my understanding where I probably overly used classes and probably about to enter one where I overly use interfaces. Of course this only really matters in static languages where you have to worry about types. Maybe I'm over thinking things...or maybe I should just go back to Ruby or Python.