Every object has an exposed interface. A collection has Add, Remove, At, etc. A socket may have Send, Receive, Close and so on.
Every object you can actually get a reference to has a concrete implementation of these interfaces.
Both of these things are obvious, however what is somewhat less obvious...
Your code shouldn't rely on the implementation details of an object, just its published interface.
If you take it to an extreme, you'd only code against Collection and so on (rather than ArrayList). More practically, just make sure you could swap in something conceptually identical without breaking your code.
To hammer out the Collection example: you have a collection of something, you're actually using ArrayList because why not. You should make sure you're code isn't going to break if, say, you end up using LinkedList in the future.