Что бы понять в чем разница между абстрактными классами и интерфейсами для начала стоит немного отойти от их реализации для конкретного языка программирования и понять их суть.
Что такое интерфейс? это спецификация взаимодействия внешнего мира с объектом. Обратите внимание именно ВЗАИМОДЕЙСТВИЯ, а не реализации.
Возьмем для примера обычный класс, описывающий какой нибудь выключатель (т.е. задача такого класса включать или выключать какое-то устройство):
public class Switch
{
public void On()
{
// тут предполагается куча кода для включения устройства
}
public void Off()
{
// тут предполагается куча кода для выключения устройства
}
}
Что входит в состав данного класса:
1. РЕАЛИЗАЦИЯ функционала включения/выключения устройства (т.е. куча кода который управляет устройством)
2. ИНТЕРФЕЙС (сигнатура методов On и Off), с помощью которого клиенты класса взаимодействуют с ним.
Вы можете спокойно управлять объектом этого выключателя, опираясь на его интерфейс, зная что есть метод On отвечающий за включение и метод Off отвечающий за выключение. Но теперь представьте что у Вас десятки разных типов выключателей с разной реализацией и над классом для каждого типа работает отдельный разработчик. Как сделать Ваш алгоритм управления универсальным и независимым от конкретного типа выключателя? Для этого нужно что бы у выключателя в независимости от его типа был одинаковый интерфейс (грубо говоря присутствовал метод On и метод Off). Но как разработчикам классов-выключателей знать что Вам нужен именно такой интерфейс? а если они и знают как заставить их его в точности соблюсти? Согласитесь было бы удобно, если бы была возможность, где-то отдельно описать интерфейс (формализовать его), на который можно было бы опираться при взаимодействии с выключателями, а другие разработчики просто бы его подключали и реализовывали. Вот тут на помощь уже и приходить отдельная конструкция interface, которая позволяет этого добиться. Вы можете сделать так:
public interface ISwithable
{
public void On()
public void Off()
}
это позволит Вам работать исключительно с интерфейсом, не парясь о конкретных реализациях, а так же сторонним разработчикам четко соблюдать необходимые Вам правила.
Теперь давайте обсудим что же такое класс. Как видно из примера класс это реализация определенного интерфейса и непосредственно конкретного функционала. А чем отличается абстрактный класс от обычного? тем что он позволяет сделать отложенную реализацию части функционала, т.е. переложить ответственность за реализацию на своих потомков. Но тем не менее он по прежнему не только реализовывает интерфейс но описывает функционал. Конечно можно с помощью абстрактного класса сделать некую имитацию только интерфейса сделав все методы абстрактными, но это не совсем правильно т.к. задачи абстрактного класса в первую очередь - это создание возможностей отложенной реализации конкретного функционала.