Есть ли какие-то практические ситуации программирования, когда кто-то может объявить абстрактный класс, когда все методы в нем конкретны?




Абстрактный класс - это класс, который объявлен абстрактным - он может включать или не включать абстрактные методы. Их нельзя создать, поэтому, если у вас есть абстрактный класс с конкретными методами, его можно создать подклассом, а затем создать экземпляр подкласса.
Что ж, вы могли бы использовать шаблон метода шаблона, где есть несколько точек переопределения, каждая из которых имеет реализации по умолчанию, но где комбинированные реализации по умолчанию сами по себе не являются законными - любая функциональная реализация должна иметь подкласс.
(И да, мне не нравится шаблон метода шаблона;))
Это очень сильно ограничивает дизайн и вызывает неприятные обходные пути, когда все оказывается не совсем так, как вы думали. Это также имеет тенденцию создавать очень загрязненные иерархии классов, а также множество странных связей.
Хороший вопрос :)
Одно можно сказать наверняка ... это, безусловно, возможно. Предложение шаблона от krosenvold - одна из веских причин для этого.
Я просто хочу сказать, что класс нельзя объявлять abstract только для предотвращения его создания.
Об этом говорится в Спецификации языка Java Раздел 8.1.1.1.
Ваша ссылка должна быть изменена: 8.1.1.1. абстрактные классы или 8.8.10. Предотвращение создания класса
Представьте себе интерфейс, объявленные методы которого при реализации обычно демонстрируют то же поведение по умолчанию. При написании класса, который должен поддерживать интерфейс, вы должны снова и снова определять указанное поведение по умолчанию.
Чтобы облегчить реализацию ваших конкретных классов, вы можете захотеть предоставить абстрактный класс, обеспечивающий поведение по умолчанию для каждого метода. Для поддержки интерфейса в конкретном классе вы можете унаследовать его от абстрактного класса и переопределить методы, если они отклоняются от стандартного поведения. Таким образом вы избежите повторной реализации одного и того же (избыточного) поведения по умолчанию.
Когда у вас есть важный класс, но система не может создать экземпляр этого класса, потому что
Другой возможный вариант использования - декоратор, который делегирует все вызовы обернутому экземпляру. Конкретная реализация декоратора может переопределять только те методы, в которые добавлена функциональность:
public interface Foo {
public void bar();
}
public abstract class FooDecorator implements Foo {
private final Foo wrapped;
public FooDecorator(Foo wrapped) { this.wrapped = wrapped; }
public void bar() { wrapped.bar(); }
}
public class TracingFoo extends FooDecorator {
//Omitting constructor code...
public void bar() {
log("Entering bar()");
super.bar();
log("Exiting bar()");
}
}
Хотя я действительно не вижу необходимости объявлять FooDecorator абстрактным (не абстрактный пример: HttpServletRequestWrapper).
Предыдущие ответы уже касались основных проблем, но есть небольшая деталь, о которой, возможно, стоит упомянуть.
У вас может быть фабрика, которая возвращает экземпляры (скрытых) подклассов абстрактного класса. Абстрактный класс определяет контракт для результирующего объекта, а также предоставляет реализации по умолчанию, но тот факт, что класс является абстрактным, не позволяет ему создавать экземпляр напрямую, а также сигнализирует о том, что идентичность «реального» класса реализации не опубликовано.
Интересно, почему никто не указал на практический пример MouseAdapter:
http://docs.oracle.com/javase/6/docs/api/java/awt/event/MouseAdapter.html
An abstract adapter class for receiving mouse events. The methods in this class are empty. This class exists as convenience for creating listener objects.
Пример сервлета:
Все методы конкретны, но базовый класс бесполезен сам по себе:
DeleteAuthor.java
DeleteAuthorХранитьBook.java
DeleteAuthorГоретьBook.java
Что не нравится в шаблоне шаблонного метода? Конечно, им можно злоупотреблять, но при разумном использовании я нахожу их весьма полезными.