Представь у тебя есть какой-нибудь метод, который принимает в агрументах объект, например, типа User
doSomething(User user)
Ты можешь передавать в этот метод любой объект типа User или объекты классов, наследующих User.
Но можно сделать еще гибче, например описать некий интерфейс UserInteface и указать в определении метода его:
doSomething(UserInterface user)
Теперь ты можешь передавать в метод объект любого класса, который реализует интерфейс UserInterface.
Разумеется, изначальный класс User из этого примера тоже должен реализовывать этот интерфейс.
То есть, указывая в типе данных параметра какой-то конкретный класс, ты привязываешься к этому классу или его наследникам, а указывая интерфейс ты привязываешься к этому интерфейсу, который может реализовать любой другой класс, связность уменьшается, а это хорошо. А если ты в этих, еще не написанных классах будешь просто писать нужные методы, то не сможешь объект этих классов использовать, тип данных то будет другой, хотя методы и будут описаны.
И, как уже написали выше, один класс может реализовывать несколько интерфейсов.