Абстрактный класс со всеми конкретными методами

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
17
0
16 307
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Абстрактный класс - это класс, который объявлен абстрактным - он может включать или не включать абстрактные методы. Их нельзя создать, поэтому, если у вас есть абстрактный класс с конкретными методами, его можно создать подклассом, а затем создать экземпляр подкласса.

Ответ принят как подходящий

Что ж, вы могли бы использовать шаблон метода шаблона, где есть несколько точек переопределения, каждая из которых имеет реализации по умолчанию, но где комбинированные реализации по умолчанию сами по себе не являются законными - любая функциональная реализация должна иметь подкласс.

(И да, мне не нравится шаблон метода шаблона;))

Что не нравится в шаблоне шаблонного метода? Конечно, им можно злоупотреблять, но при разумном использовании я нахожу их весьма полезными.

Ilja Preuß 12.12.2008 14:59

Это очень сильно ограничивает дизайн и вызывает неприятные обходные пути, когда все оказывается не совсем так, как вы думали. Это также имеет тенденцию создавать очень загрязненные иерархии классов, а также множество странных связей.

krosenvold 12.12.2008 15:17

Хороший вопрос :)

Одно можно сказать наверняка ... это, безусловно, возможно. Предложение шаблона от krosenvold - одна из веских причин для этого.

Я просто хочу сказать, что класс нельзя объявлять abstract только для предотвращения его создания.

Об этом говорится в Спецификации языка Java Раздел 8.1.1.1.

Ваша ссылка должна быть изменена: 8.1.1.1. абстрактные классы или 8.8.10. Предотвращение создания класса

Sk8erPeter 15.01.2013 05:03

Представьте себе интерфейс, объявленные методы которого при реализации обычно демонстрируют то же поведение по умолчанию. При написании класса, который должен поддерживать интерфейс, вы должны снова и снова определять указанное поведение по умолчанию.

Чтобы облегчить реализацию ваших конкретных классов, вы можете захотеть предоставить абстрактный класс, обеспечивающий поведение по умолчанию для каждого метода. Для поддержки интерфейса в конкретном классе вы можете унаследовать его от абстрактного класса и переопределить методы, если они отклоняются от стандартного поведения. Таким образом вы избежите повторной реализации одного и того же (избыточного) поведения по умолчанию.

Когда у вас есть важный класс, но система не может создать экземпляр этого класса, потому что

  • этот класс является родительским для множества классов системы;
  • у этого есть большая ответственность (методы, используемые множеством классов) для требований домена;
  • этот класс не представляет собой конкретный объект;

Другой возможный вариант использования - декоратор, который делегирует все вызовы обернутому экземпляру. Конкретная реализация декоратора может переопределять только те методы, в которые добавлена ​​функциональность:

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

  1. Абстрактный класс с конкретным методом doGet.
  2. doGet вызывает файл, указанный в строке защищенный sql_path.
  3. sql_path имеет значение null.

DeleteAuthorХранитьBook.java

  1. расширяет абстрактный класс DeleteAuthor
  2. устанавливает sql_path в delete_author_ХРАНИТЬ_BOOK.sql

DeleteAuthorГоретьBook.java

  1. расширяет абстрактный класс DeleteAuthor
  2. устанавливает sql_path в delete_author_ГОРЕТЬ_BOOK.sql

Другие вопросы по теме