Each class should have only one sole purpose, and not filled with excessive functionality.
Classes should be open for extensions, closed for modifications. You should not have to rewrite an existing class for implementing a new feature.
This means that every subclass or derived class should be substitutable for their base or parent class.
Interfaces should not force classes to implement what they can not do. Large interfaces should be divided into small ones.
Components should depend on abstractions, not on concrete objects.