Что такое «абстрактный класс» в Java?
Что такое «абстрактный класс» в Java?
Ответы:
Абстрактный класс - это класс, который не может быть создан. Абстрактный класс используется путем создания наследующего подкласса, который может быть создан. Абстрактный класс делает несколько вещей для наследующего подкласса:
Вот пример:
abstract public class AbstractClass
{
abstract public void abstractMethod();
public void implementedMethod() { System.out.print("implementedMethod()"); }
final public void finalMethod() { System.out.print("finalMethod()"); }
}
Обратите внимание, что у abstractMethod () нет тела метода. Из-за этого вы не можете сделать следующее:
public class ImplementingClass extends AbstractClass
{
// ERROR!
}
Там нет метода, который реализует abstractMethod()
! Так что у JVM нет возможности узнать, что она должна делать, когда получит что-то вродеnew ImplementingClass().abstractMethod()
.
Вот правильный ImplementingClass
.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
}
Обратите внимание, что вам не нужно определять implementedMethod()
или finalMethod()
. Они уже были определеныAbstractClass
.
Вот еще один правильный ImplementingClass
.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
В этом случае вы переопределили implementedMethod()
.
Однако из-за final
ключевого слова следующее невозможно.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
public void finalMethod() { System.out.print("ERROR!"); }
}
Вы не можете сделать это, потому что реализация finalMethod()
in AbstractClass
помечена как окончательная реализацияfinalMethod()
: никакие другие реализации не будут разрешены, никогда.
Теперь вы также можете дважды реализовать абстрактный класс:
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
// In a separate file.
public class SecondImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("second abstractMethod()"); }
}
Теперь где-то вы могли бы написать другой метод.
public tryItOut()
{
ImplementingClass a = new ImplementingClass();
AbstractClass b = new ImplementingClass();
a.abstractMethod(); // prints "abstractMethod()"
a.implementedMethod(); // prints "Overridden!" <-- same
a.finalMethod(); // prints "finalMethod()"
b.abstractMethod(); // prints "abstractMethod()"
b.implementedMethod(); // prints "Overridden!" <-- same
b.finalMethod(); // prints "finalMethod()"
SecondImplementingClass c = new SecondImplementingClass();
AbstractClass d = new SecondImplementingClass();
c.abstractMethod(); // prints "second abstractMethod()"
c.implementedMethod(); // prints "implementedMethod()"
c.finalMethod(); // prints "finalMethod()"
d.abstractMethod(); // prints "second abstractMethod()"
d.implementedMethod(); // prints "implementedMethod()"
d.finalMethod(); // prints "finalMethod()"
}
Обратите внимание , что даже если мы объявили b
в AbstractClass
тип, он отображает "Overriden!"
. Это потому, что объект, который мы создали ImplementingClass
, былimplementedMethod()
конечно, переопределен. (Возможно, вы видели, что это называется полиморфизмом.)
Если мы хотим получить доступ к члену, специфичному для определенного подкласса, мы должны сначала обратиться к этому подклассу:
// Say ImplementingClass also contains uniqueMethod()
// To access it, we use a cast to tell the runtime which type the object is
AbstractClass b = new ImplementingClass();
((ImplementingClass)b).uniqueMethod();
Наконец, вы не можете сделать следующее:
public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
... // implementation
}
Только один класс может быть продлен за один раз. Если вам нужно расширить несколько классов, они должны быть интерфейсами. Ты можешь сделать это:
public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
... // implementation
}
Вот пример интерфейса:
interface InterfaceA
{
void interfaceMethod();
}
Это в основном так же, как:
abstract public class InterfaceA
{
abstract public void interfaceMethod();
}
Разница лишь в том, что второй способ не дает компилятору понять, что это на самом деле интерфейс. Это может быть полезно, если вы хотите, чтобы люди реализовывали только ваш интерфейс, а не другие. Однако, как правило, если у вашего абстрактного класса есть только абстрактные методы, вы, вероятно, должны сделать его интерфейсом.
Следующее является незаконным:
interface InterfaceB
{
void interfaceMethod() { System.out.print("ERROR!"); }
}
Вы не можете реализовать методы в интерфейсе. Это означает, что если вы реализуете два разных интерфейса, разные методы в этих интерфейсах не могут конфликтовать. Поскольку все методы в интерфейсе являются абстрактными, вы должны реализовать метод, и поскольку ваш метод является единственной реализацией в дереве наследования, компилятор знает, что он должен использовать ваш метод.
c.implementedMethod()
печатать "Переопределено!"? SecondImplementingClass
не отменяет implementedMethod()
.
Класс Java становится абстрактным при следующих условиях:
1. По крайней мере один из методов помечен как абстрактный:
public abstract void myMethod()
В этом случае компилятор заставляет вас пометить весь класс как абстрактный.
2. Класс помечается как абстрактный:
abstract class MyClass
Как уже было сказано: если у вас есть абстрактный метод, компилятор заставляет вас пометить весь класс как абстрактный. Но даже если у вас нет абстрактного метода, вы все равно можете пометить класс как абстрактный.
Общего пользования:
Обычное использование абстрактных классов - предоставить схему класса, похожего на интерфейс. Но, в отличие от интерфейса, он уже может обеспечивать функциональность, то есть некоторые части класса реализованы, а некоторые просто обозначены объявлением метода. ("Аннотация")
Абстрактный класс не может быть создан, но вы можете создать конкретный класс на основе абстрактного класса, который затем может быть создан. Для этого вы должны наследовать от абстрактного класса и переопределять абстрактные методы, то есть реализовывать их.
abstract
ключевое слово - это все, что необходимо для того, чтобы класс был абстрактным. Но конкретный класс не может содержать abstract
метод . Таким образом, если у вашего класса есть abstract
метод, он должен быть объявлен как abstract
класс компилятору.
Класс, который объявлен с использованием абстрактного ключевого слова, известен как abstract class
. Абстракция - это процесс сокрытия деталей реализации данных и отображения только функциональности для пользователя. Абстракция позволяет вам сосредоточиться на том, что делает объект, а не на том, как он это делает.
Основные вещи абстрактного класса
Абстрактный класс может содержать или не содержать абстрактные методы. Это могут быть не абстрактные методы.
Абстрактный метод - это метод, который объявлен без реализации (без фигурных скобок и сопровождается точкой с запятой), например:
пример: abstract void moveTo(double deltaX, double deltaY);
Если у класса есть хотя бы один абстрактный метод, тогда этот класс должен быть абстрактным
Абстрактные классы не могут быть созданы (вы не можете создавать объекты класса Abstract)
Чтобы использовать абстрактный класс, вы должны наследовать его от другого класса. Предоставить реализации для всех абстрактных методов в нем.
Если вы наследуете абстрактный класс, вы должны предоставить реализации для всех абстрактных методов в нем.
Объявите абстрактный класс
Указывая abstract
ключевое слово перед классом во время объявления, он становится абстрактным. Посмотрите на код ниже:
abstract class AbstractDemo{ }
Объявите абстрактный метод
Указание abstract
ключевого слова перед методом во время объявления делает его абстрактным. Посмотрите на код ниже,
abstract void moveTo();//no body
Почему нам нужно абстрагировать классы
В объектно-ориентированном приложении для рисования вы можете рисовать круги, прямоугольники, линии, кривые Безье и многие другие графические объекты. Все эти объекты имеют определенные состояния (например, положение, ориентация, цвет линии, цвет заливки) и общее поведение (например, перемещение, поворот, изменение размера, рисование). Некоторые из этих состояний и поведения одинаковы для всех графических объектов (например, цвет заливки, положение и перемещение). Другие требуют другой реализации (например, изменить размер или нарисовать). Все графические объекты должны уметь рисовать или изменять размеры сами, они просто отличаются тем, как они это делают.
Это идеальная ситуация для абстрактного суперкласса. Вы можете воспользоваться сходствами и объявить все графические объекты наследуемыми от того же абстрактного родительского объекта (например, :), GraphicObject
как показано на следующем рисунке.
Сначала вы объявляете абстрактный класс GraphicObject
для предоставления переменных-членов и методов, которые полностью используются всеми подклассами, такими как текущая позиция и метод moveTo. GraphicObject
также объявлены абстрактные методы, такие как рисование или изменение размера, которые должны быть реализованы всеми подклассами, но должны быть реализованы различными способами. GraphicObject
Класс может выглядеть следующим образом :
abstract class GraphicObject {
void moveTo(int x, int y) {
// Inside this method we have to change the position of the graphic
// object according to x,y
// This is the same in every GraphicObject. Then we can implement here.
}
abstract void draw(); // But every GraphicObject drawing case is
// unique, not common. Then we have to create that
// case inside each class. Then create these
// methods as abstract
abstract void resize();
}
Использование абстрактного метода в суб классов
каждого не абстрактные подклассы GraphicObject
, такие как Circle
и Rectangle
, должны обеспечивать реализацию для draw
и resize
методов.
class Circle extends GraphicObject {
void draw() {
//Add to some implementation here
}
void resize() {
//Add to some implementation here
}
}
class Rectangle extends GraphicObject {
void draw() {
//Add to some implementation here
}
void resize() {
//Add to some implementation here
}
}
Внутри main
метода вы можете вызвать все методы следующим образом:
public static void main(String args[]){
GraphicObject c = new Circle();
c.draw();
c.resize();
c.moveTo(4,5);
}
Способы достижения абстракции в Java
Есть два способа добиться абстракции в Java
Абстрактный класс с конструкторами, членами данных, методами и т. Д.
abstract class GraphicObject {
GraphicObject (){
System.out.println("GraphicObject is created");
}
void moveTo(int y, int x) {
System.out.println("Change position according to "+ x+ " and " + y);
}
abstract void draw();
}
class Circle extends GraphicObject {
void draw() {
System.out.println("Draw the Circle");
}
}
class TestAbstract {
public static void main(String args[]){
GraphicObject grObj = new Circle ();
grObj.draw();
grObj.moveTo(4,6);
}
}
Вывод:
GraphicObject is created
Draw the Circle
Change position according to 6 and 4
Помните два правила:
Если в классе мало абстрактных методов и мало конкретных методов, объявите его как abstract
класс.
Если класс имеет только абстрактные методы, объявите его как interface
.
Ссылки:
Это класс, который не может быть создан, и вынуждает реализацию классов, возможно, реализовывать абстрактные методы, которые он выделяет.
Проще говоря, вы можете думать об абстрактном классе как об интерфейсе с немного большими возможностями.
Вы не можете создать экземпляр интерфейса, который также имеет место для абстрактного класса.
В вашем интерфейсе вы можете просто определить заголовки методов, и ВСЕ разработчики будут вынуждены реализовать их все . В абстрактном классе вы также можете определить заголовки вашего метода, но здесь - в отличие от интерфейса - вы также можете определить тело (обычно реализация по умолчанию) метода. Более того, когда другие классы расширяют (обратите внимание, не реализуют и, следовательно, вы также можете иметь только один абстрактный класс на дочерний класс) вашего абстрактного класса, они не будут вынуждены реализовывать все ваши методы вашего абстрактного класса, если вы не указали абстрактный метод ( в таком случае это работает как для интерфейсов, вы не можете определить тело метода).
public abstract class MyAbstractClass{
public abstract void DoSomething();
}
В противном случае для обычных методов абстрактного класса «наследники» могут либо просто использовать поведение по умолчанию, либо переопределить его, как обычно.
Пример:
public abstract class MyAbstractClass{
public int CalculateCost(int amount){
//do some default calculations
//this can be overriden by subclasses if needed
}
//this MUST be implemented by subclasses
public abstract void DoSomething();
}
Из оракульной документации
Абстрактные методы и классы:
Абстрактный класс - это класс, который объявлен как абстрактный - он может включать или не включать абстрактные методы
Абстрактные классы не могут быть созданы, но они могут быть разделены на подклассы
Абстрактный метод - это метод, который объявлен без реализации (без фигурных скобок и сопровождается точкой с запятой), например так:
abstract void moveTo(double deltaX, double deltaY);
Если класс включает абстрактные методы, то сам класс должен быть объявлен абстрактным, как в:
public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}
Когда абстрактный класс является подклассом, подкласс обычно обеспечивает реализации для всех абстрактных методов в своем родительском классе. Однако, если это не так, то подкласс также должен быть объявлен абстрактным .
Поскольку abstract classes
и interfaces
связаны, взгляните на ниже вопросы SE:
В чем разница между интерфейсом и абстрактным классом?
Как мне объяснить разницу между интерфейсом и абстрактным классом?
Получите ваши ответы здесь:
Абстрактный класс против интерфейса в Java
Может ли абстрактный класс иметь конечный метод?
Кстати, это вопрос, который вы задали недавно. Подумайте о новом вопросе для создания репутации ...
Редактировать:
Только что понял, что постеры этого и упомянутых вопросов имеют одинаковое или хотя бы похожее имя, но идентификатор пользователя всегда различен. Так что либо есть техническая проблема, у кейера возникают проблемы с повторным входом в систему и поиском ответов на его вопросы, либо это своего рода игра для развлечения сообщества SO;)
Маленькое дополнение ко всем этим постам.
Иногда вы можете объявить класс, но не знаете, как определить все методы, принадлежащие этому классу. Например, вы можете объявить класс с именем Writer и включить в него метод-член с именем write () . Однако вы не знаете, как написать () код, потому что он отличается для каждого типа устройств записи. Конечно, вы планируете справиться с этим путем создания подкласса Writer, такого как принтер, диск, сеть и консоль.
Абстрактный класс не может быть непосредственно создан, но должен быть получен из, чтобы его можно было использовать. Класс ДОЛЖЕН быть абстрактным, если он содержит абстрактные методы: либо напрямую
abstract class Foo {
abstract void someMethod();
}
или косвенно
interface IFoo {
void someMethod();
}
abstract class Foo2 implements IFoo {
}
Однако класс может быть абстрактным, не содержащим абстрактных методов. Это способ предотвратить прямую инстанцию, например,
abstract class Foo3 {
}
class Bar extends Foo3 {
}
Foo3 myVar = new Foo3(); // illegal! class is abstract
Foo3 myVar = new Bar(); // allowed!
Последний стиль абстрактных классов может использоваться для создания «интерфейсоподобных» классов. В отличие от интерфейсов, абстрактный класс может содержать неабстрактные методы и переменные экземпляра. Вы можете использовать это для предоставления некоторых базовых функций расширению классов.
Другой частый шаблон заключается в реализации основных функций в абстрактном классе и определении части алгоритма в абстрактном методе, который будет реализован расширяемым классом. Глупый пример:
abstract class Processor {
protected abstract int[] filterInput(int[] unfiltered);
public int process(int[] values) {
int[] filtered = filterInput(values);
// do something with filtered input
}
}
class EvenValues extends Processor {
protected int[] filterInput(int[] unfiltered) {
// remove odd numbers
}
}
class OddValues extends Processor {
protected int[] filterInput(int[] unfiltered) {
// remove even numbers
}
}
public abstract class Place {
String Name;
String Postcode;
String County;
String Area;
Place () {
}
public static Place make(String Incoming) {
if (Incoming.length() < 61) return (null);
String Name = (Incoming.substring(4,26)).trim();
String County = (Incoming.substring(27,48)).trim();
String Postcode = (Incoming.substring(48,61)).trim();
String Area = (Incoming.substring(61)).trim();
Place created;
if (Name.equalsIgnoreCase(Area)) {
created = new Area(Area,County,Postcode);
} else {
created = new District(Name,County,Postcode,Area);
}
return (created);
}
public String getName() {
return (Name);
}
public String getPostcode() {
return (Postcode);
}
public String getCounty() {
return (County);
}
public abstract String getArea();
}
Абстрактный класс - это класс, который объявлен абстрактным - он может включать или не включать абстрактные методы. Абстрактные классы не могут быть созданы, но они могут быть разделены на подклассы.
Другими словами, класс, который объявлен с абстрактным ключевым словом, известен как абстрактный класс в Java. Он может иметь абстрактный (метод без тела) и неабстрактный методы (метод с телом).
Важное примечание: - Абстрактные классы нельзя использовать для создания экземпляров объектов, их можно использовать для создания ссылок на объекты, поскольку подход Java к полиморфизму во время выполнения реализован с использованием ссылок на суперклассы. Таким образом, должна быть возможность создать ссылку на абстрактный класс, чтобы его можно было использовать для указания на объект подкласса. Вы увидите эту функцию в следующем примере
abstract class Bike{
abstract void run();
}
class Honda4 extends Bike{
void run(){
System.out.println("running safely..");
}
public static void main(String args[]){
Bike obj = new Honda4();
obj.run();
}
}
Абстрактный класс - это класс, который не полностью реализован, но предоставляет что-то вроде схемы для подклассов. Он может быть частично реализован тем, что содержит полностью определенные конкретные методы, но он также может содержать абстрактные методы. Это методы с сигнатурой, но без тела метода. Любой подкласс должен определять тело для каждого абстрактного метода, в противном случае он также должен быть объявлен абстрактным. Поскольку абстрактные классы не могут быть созданы, они должны быть расширены как минимум на один подкласс, чтобы их можно было использовать. Думайте об абстрактном классе как об общем классе, и подклассы должны заполнить недостающую информацию.
Класс, который может иметь как конкретные, так и не конкретные методы, т.е. с телом и без.
Он ничего не делает, просто предоставляет общий шаблон, который будет использоваться для его подкласса