Regarding classes, I like to provide a class summary stating the intent and purpose. Accessors, Mutators, Constructors – I don’t feel the need to comment them as their roles are (and should be) rather self-explanatory. Non boiler-plate methods, however, receive a similar, but more succinct, documentation, perhaps with some implementation context if needed (Interface and Abstract Class implementation.
I comment Interfaces in a much similar way to Classes, with focus on the intent of the responsibility that the interface is capturing as well as hints on how to best use it.
As for inline commenting, I try to keep it to a minimal, used sparingly for algorithms, complex blocks, etc. Arguably, if implementation description is needed for complex blocks, it is likely that your method needs to be refined and abstracted further.
All in all, a program should really only be commented as much as they need be, and no more – it becomes rather silly when more /* blah blah */ than code is found in a source file. What is greatly undervalued is the intuitiveness of good code through naming conventions and clear intent of what is being done. I’m a proponent of good code reading like a story; easy to comprehend and with clear purpose.
I found the book Clean Code to be very insightful and recommend it to any developer interested in taking their code quality to the next level. Read my blog where I discuss this book, you too may find it as insightful as I have.