since we know that free communication can reach through the implementation of the interface, and inheritance makes a tight couple.
I think you are wrong. “Binding” usually consists of about two different classes that know each other either by their specific class, or simply by some interface.
Say 2 classes A and B must communicate with each other.
A <--knows--> B
Methods in will have some parameter B, and methods from B have a parameter of type A. For example. as
class A { public void talkTo(B b) {} }
Now that there is a tight connection between A and B, because every change you make to these classes can make changes to another class.
If you do it weakly, they both expose themselves through some kind of interface. (An “interface” may also mean an abstract class — this is the choice of the appropriate side.)
IA <-- A ^ | \ / X < loose coupling between the A side and the B side / \ v | IB <-- B < pretty tight coupling betwen IB and B
and the connection between them goes through these interfaces
class A implements IA { public void talkTo(IB b); } class B implements IB { public void talkTo(IA a); }
The relationship between A and IA (what you seem to be looking at) is not something that is closely related to loose communication. There are some similarities, but a loose connection does not mean that you must implement an interface and extend an abstract class. It is usually better to implement only the interface.
If you can replace the "IS A" relationship with the "HAS A" relationship, you are essentially doing the same thing. You separate yourself (for example, from you) from a specific implementation and only have to depend on the encapsulated other side (for example, from B). Inheritance is indeed a very powerful feature, but is often used incorrectly.