One piece of advice I wish had been given to me a long time ago is:
Don't over-use inheritance.
This is a really easy pitfall for a beginner (imho) as it is one of the big concepts in OOP that everyone talks about.
Basically, you should be using inheritance only where it really really makes sense - think data types, some widget hierarchies, stuff where the is-a relationship is so obvious anybody would have used it. Otherwise you should be injecting objects into others and calling them in order to change functionality (composition).
Do not be tempted to just define a load of abstract methods and override multiple times to implement them differently when you could have a single class and inject (argument to constructor) an object implementing an interface that you call to do whatever variable functionality that you would otherwise have put in the abstract methods.
This will lead to much simpler and more reusable code (in my experience), and more testable too.