Это приближает интерфейсы Java к примесям.
1. Очень часто бывает, что у какой-то функции есть реализация, опирающаяся на другие функции — либо базовая неоптимальная, либо вообще единственно возможная. Чаще всего это избыточные функции-утилиты. Пишу на Си++
class Stream {
public:
virtual void write(size_t length, const void* data) = 0;
// пишет в поток word в машинном порядке байтов
void writeW(uint16_t data) {
write(2, &data);
}
};
За что вообще так ненавидят множественное наследование? За дублирование данных! Вот у нас некая штука, без единого поля данных — почему в Java она класс, а не интерфейс?
2. Какую-то функцию переопределяют настолько редко, что лучше сделать ей реализацию на месте. Опять Си++.
class ErpConnector {
public:
// 80% модулей не могут экспортировать данные в систему управления
// предприятием — напишем базовую реализацию.
virtual bool canExportData() const { return false; }
virtual void exportData() const {}
};
3. И просто документирование, как оно должно себя вести :) Из реального проекта, снова Си++.
void im::DateGrouper::toFirstDateOfPeriod(dt::Date& aDate, int aStart) const
{
aDate = toDate(toInt(aDate, aStart), aStart);
}
Класс служит для группировки дат в периоды (недели, месяцы, годы). aStart — это дополнительный int, позволяющий начать год с февраля или месяц с 15-го. Эта функция переводит дату «на месте» в первую дату периода. Она крайне неоптимальна (дату в число, затем число опять в дату) и потому переписана почти во всех в реализациях.
void im::MonthGrouper::toFirstDateOfPeriod(dt::Date& aDate, int aStart) const
{
if (aDate.day < aStart)
aDate.addMonthsMechanical(-1); // механически вычесть 1 месяц; дата может стать неверной.
aDate.day = aStart;
aDate.fixupTo1(); // неверную дату привести к 1-му числу следующего месяца
}
Но по крайней мере понятно, как она должна работать.