Почему HTTPServlet является абстрактным классом? Любая функциональная причина?
HttpServlet
абстрактный класс со всеми реализованными методами Почему это абстрактно?
Самый распространенный ответ, который я получил, состоит в том, чтобы ограничить создание HttpServlet
, Но есть и другие способы сделать это, например, частный конструктор ограничит создание экземпляра.
Я могу понять, что они следуют шаблону шаблона проектирования. Если некоторые методы являются абстрактными, пользователь в конечном итоге реализует их все, даже если он не нужен им для его бизнес-логики.
Но если HttpServlet
не был абстрактным, пользователь все еще может расширить его и переопределить методы require.
По крайней мере, по словарному значению слова "абстрактный", для меня не имеет никакого смысла иметь абстрактный класс со всеми реализованными методами.
Да, комбинация абстрактных и конкретных методов вполне приемлема.
Но если вы делаете класс абстрактным, почему бы не сделать те методы абстрактными, которые подкласс должен переопределить? или, может быть, вообще не объявлять его абстрактным?
подобно doGet()
или же doPost()
это случай
6 ответов
Чтобы иметь какое-либо полезное поведение, ожидается, что вам придется переопределить методы. HttpServlet сам по себе не имеет полезных функций.
Закрытие его конструкторов ограничит возможность создания подклассов.
Конструкция HttpServlet, вероятно, была не идеальной - поскольку на многих страницах, особенно в формах, логика GET и POST должна проходить хотя бы частично по общему пути. Идея дизайна HttpServlet, однако, должна была предложить doGet()
, doPost()
реализации и т. д., отвечающие на ошибку "не поддерживается" в зависимости от версии HTTP. Эти заглушки было бы полезно наследовать, если вам нужно было вернуть такой ответ.
Таким образом, API/ интерфейс завершен - но функциональность определенно нет. Таким образом, он объявлен как абстрактный.
HTTPServlet - это абстрактный класс со всеми реализованными методами. Тогда почему это абстрактно?
Это абстрактно, потому что реализации ключевых методов должны быть предоставлены (например, переопределены) пользовательским классом сервлета. Как говорит Javadoc:
Подкласс HttpServlet должен переопределить хотя бы один метод, обычно один из них:
- doGet, если сервлет поддерживает запросы HTTP GET
- doPost, для запросов HTTP POST
- doPut, для запросов HTTP PUT
- doDelete, для запросов HTTP DELETE
- инициализировать и уничтожать, чтобы управлять ресурсами, которые удерживаются для жизни сервлета
- getServletInfo, который использует сервлет для предоставления информации о себе
Если вы расширите класс без переопределения каких-либо методов, вы получите бесполезный сервлет; то есть тот, который дает сообщение об ошибке для всех запросов. Точно так же, если класс не был abstract
то любой прямой случай HttpServlet
было бы бесполезно.
Следовательно, причина для HttpServlet
учебный класс abstract
заключается в предотвращении (наивной) ошибки программиста.
Для справки, причина предоставления реализаций всех методов состоит в том, чтобы сделать жизнь программиста проще, обеспечив поведение по умолчанию. Например, если я не хочу, чтобы мой сервлет поддерживал запросы DELETE, реализация по умолчанию для doDelete
будет удобно отправить ответ с кодом ответа "Метод не поддерживается".
Вы вынуждены расширить HttpServlet, потому что вам необходимо добавить в него логику, специфичную для вашего приложения. Вот определение абстрактного класса в соответствии с людьми оракула:
"Абстрактный класс - это класс, который объявлен как абстрактный - он может включать или не включать абстрактные методы. Абстрактные классы не могут быть созданы, но они могут быть разделены на подклассы".
http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
Причина: мы все знаем, что HttpServlet не имеет какого-либо абстрактного метода. Он содержит все конкретные методы. Но этот класс все еще остается абстрактным. Причина очень проста. Наш собственный класс может выступать в качестве сервлета, только когда он расширяет класс HttpServlet или GenericServlet или реализует интерфейс сервлета. Если класс HttpServlet не будет оставаться абстрактным, вы не будете заинтересованы в расширении этого класса, и ваш класс не будет действовать как сервлет.
ServletContainer использует instanceOf(), чтобы узнать, является ли ваш класс дочерним по отношению к интерфейсу HttpServlet,GenericServlet или Servlet. Поскольку ваш класс не является потомком HttpServlet, класса GenericServlet или реализованного интерфейса Servlet,instanceOf() завершится с ошибкой.
Есть две причины для этого.
- Во-первых, чтобы вы не могли создать объект класса HttpServlet. Предположим, что он не защищен, тогда мы могли бы создать объект этого класса, который был бы бесполезен.
- Второе Есть защищенный метод в классе HttpServlet. Таким образом, чтобы получить доступ к защищенному объекту класса, чтобы иметь функцию Servlet в вашем классе реализации, вы должны расширить этот класс. Поэтому в основном это заставляет программиста расширять класс HttpServlet.
По сути, HttpServlet не содержит никакого абстрактного метода, он только реализует метод обслуживания (-,-) жизненного цикла, который является абстрактным. А также предоставляет 7 не абстрактных методов doXXX() без какой-либо логики, связанной с приложением, для отправки ошибки 404 в качестве ответа. Поэтому расширенному классу класса HTTPServlet нет необходимости реализовывать методы doXXX(), чтобы информировать разработчиков Java о том, что класс HttpServlet не является полностью реализованным классом. Класс HttpServlet выполнен как абстрактный.
В основном у нас здесь есть абстрактный класс (HttpServlet
) без какого-либо абстрактного метода или только конкретного метода. Где наш класс сервлетов реализует javax.servlet.Servlet
прямо (в случае RMI и CORBA) или косвенно (расширение родового или HTTPServlet
).
Как интерфейс имеет 3 основных метода (init()
, service()
а также destroy()
), который реализуется HttpServlet
(абстрактный класс), который расширяется вашим классом сервлетов, который обрабатывает запросы браузера, сделанные к серверу, используя эти три метода. И в зависимости от типа метода HTTP-запроса, наш класс сервлета (путем расширения HttpServlet
) использует соответствующие do[xxx]
метод, который в большинстве случаев doGet
или же doPost
, Если у нас есть все методы или некоторые методы httpServlet в качестве абстрактного метода, мы должны реализовать весь или некоторые из абстрактных методов, которые присутствуют в HttpServlet
в нашем подклассе сервлета, но мы должны реализовать только те методы, которые требуются для обработки запроса метода HTTP. Таким образом, по моему мнению, наличие конкретного метода в абстрактном классе обеспечивает свободу реализации в зависимости от логики HTTP-запроса.