Quando un'API utilizza una classe base astratta, il (solo) modo di fornire una versione di tale API è di creare una sottoclasse della classe base astratta.
Perché in C # e in Java possiamo avere solo una super classe, è, in un certo senso, una risorsa scarsa. Richiedere che ogni sottoclasse di implementatore dell'API da quella classe base astratta significhi che non possono sottoclasse da una classe di loro scelta. (Ciò significa che la sottoclasse sarà quindi una nuova classe per ciascun implementatore e che probabilmente dovrà agire come proxy per un'altra classe nella loro gerarchia.)
Quando un'API utilizza un'interfaccia, ciascun implementatore può scegliere qualsiasi classe base che desidera. Ciò significa, ad esempio, che possono implementare l'interfaccia da una classe esistente nella loro gerarchia di classi.
Pertanto, le interfacce risultano in un accoppiamento più flessibile (tra le gerarchie di classi) e una maggiore libertà di implementazione.
(Ci sono ulteriori cose da dire sull'accoppiamento più stretto se la classe astratta fornisce qualsiasi implementazione, ad esempio qualcosa oltre il metodo astratto).