Абстрактный класс на Java

Что такое "абстрактный класс" в Java?

16 ответов

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

  1. Определите методы, которые могут использоваться наследующим подклассом.
  2. Определите абстрактные методы, которые должен реализовывать наследующий подкласс.
  3. Обеспечить общий интерфейс, который позволяет подклассу обмениваться со всеми другими подклассами.

Вот пример:

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() в 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!"); }
}

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

Класс Java становится абстрактным при следующих условиях:

1. По крайней мере один из методов помечен как абстрактный:

public abstract void myMethod()

В этом случае компилятор заставляет вас пометить весь класс как абстрактный.

2. Класс помечается как абстрактный:

abstract class MyClass

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

Общего пользования:

Обычное использование абстрактных классов заключается в предоставлении схемы класса, похожего на интерфейс. Но, в отличие от интерфейса, он уже может обеспечивать функциональность, то есть некоторые части класса реализованы, а некоторые части просто обозначены объявлением метода. ("Аннотация")

Абстрактный класс не может быть создан, но вы можете создать конкретный класс на основе абстрактного класса, который затем можно создать. Для этого вы должны наследовать от абстрактного класса и переопределять абстрактные методы, т.е. реализовывать их.

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

Основные вещи абстрактного класса

  • Абстрактный класс может содержать или не содержать абстрактные методы. Это могут быть не абстрактные методы.

    Абстрактный метод - это метод, который объявлен без реализации (без фигурных скобок и сопровождается точкой с запятой), например так:

    пример: abstract void moveTo(double deltaX, double deltaY);

  • Если у класса есть хотя бы один абстрактный метод, тогда этот класс должен быть абстрактным

  • Абстрактные классы не могут быть созданы (Вы не можете создавать объекты класса Abstract)

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

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

Объявить абстрактный классabstract Ключевое слово перед классом во время объявления делает его абстрактным. Посмотрите на код ниже:

abstract class AbstractDemo{ }

Объявить абстрактный методabstract Ключевое слово перед методом во время объявления делает его абстрактным. Посмотрите на код ниже,

abstract void moveTo();//no body

Почему нам нужно абстрагировать классы

В объектно-ориентированном приложении для рисования вы можете рисовать круги, прямоугольники, линии, кривые Безье и многие другие графические объекты. Все эти объекты имеют определенные состояния (например, для: - положение, ориентация, цвет линии, цвет заливки) и общее поведение (например, для перемещения, поворота, изменения размера, рисования). Некоторые из этих состояний и поведения одинаковы для всех графических объектов (например, цвет заливки, положение и перемещение). Другие требуют другой реализации (например: изменить размер или нарисовать). Все графические объекты должны уметь рисовать или изменять размеры сами, они просто отличаются тем, как они это делают.

Это идеальная ситуация для абстрактного суперкласса. Вы можете воспользоваться сходствами и объявить все графические объекты наследуемыми от одного и того же абстрактного родительского объекта (например: GraphicObject), как показано на следующем рисунке. введите описание изображения здесь

Сначала вы объявляете абстрактный класс, GraphicObjectдля предоставления переменных-членов и методов, которые полностью используются всеми подклассами, такими как текущая позиция и метод moveTo. GraphicObject также объявлены абстрактные методы, такие как draw или resize, которые должны быть реализованы всеми подклассами, но должны быть реализованы различными способами. 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

  • Абстрактный класс (от 0 до 100%)
  • Интерфейс (100%)

Абстрактный класс с конструкторами, членами данных, методами и т. Д.

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,

Рекомендации:

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

Получите ваши ответы здесь:

Абстрактный класс против интерфейса в Java

Может ли абстрактный класс иметь конечный метод?

Кстати, это вопрос, который вы задали недавно. Подумайте о новом вопросе для создания репутации...

Редактировать:

Только что понял, что постеры этого и упомянутых вопросов имеют одинаковое или хотя бы похожее имя, но идентификатор пользователя всегда отличается. Так что либо есть техническая проблема, что у keyur возникают проблемы с повторным входом в систему и поиском ответов на его вопросы, либо это своего рода игра для развлечения сообщества SO;)

Проще говоря, вы можете думать об абстрактном классе как об интерфейсе с немного большими возможностями.

Вы не можете создать экземпляр интерфейса, который также имеет место для абстрактного класса.

В вашем интерфейсе вы можете просто определить заголовки методов, и ВСЕ разработчики будут вынуждены реализовать их все. В абстрактном классе вы также можете определить заголовки вашего метода, но здесь - в отличие от интерфейса - вы также можете определить тело (обычно реализацию по умолчанию) метода. Более того, когда другие классы расширяют (обратите внимание, не реализуют и, следовательно, вы также можете иметь только один абстрактный класс на дочерний класс) вашего абстрактного класса, они не будут вынуждены реализовывать все ваши методы вашего абстрактного класса, если вы не указали абстрактный метод (в таком случае это работает как для интерфейсов, вы не можете определить тело метода).

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:

В чем разница между интерфейсом и абстрактным классом?

Как мне объяснить разницу между интерфейсом и абстрактным классом?

Маленькое дополнение ко всем этим постам.

Иногда вы можете объявить класс, но не знаете, как определить все методы, принадлежащие этому классу. Например, вы можете объявить класс с именем 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
    }
}

Что такое абстрактный класс? Хорошо! давайте возьмем пример, вы немного знакомы с химией, у нас есть элемент углерод (символ C). У углерода есть некоторая базовая атомная структура, которую вы не можете изменить, но используя углерод, вы можете получить так много соединений, как (CO2), метан (CH4) , Бутан (C4H10).

Итак, здесь углерод - это абстрактный класс, и вы не хотите менять его базовую структуру, однако вы хотите, чтобы их дети (CO2,CH4 и т. Д.) Использовали его. Но по-своему.

Решение - базовый класс (аннотация)

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();

}

Члены класса

Абстрактный класс может иметь статические поля и статические методы. Вы можете использовать эти статические члены со ссылкой на класс (например, AbstractClass.staticMethod()) так же, как и с любым другим классом.

Не забывай это.

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

Другими словами, класс, который объявлен с абстрактным ключевым словом, известен как абстрактный класс в 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();  
    }  
} 

Абстрактный класс - это класс, который не полностью реализован, но предоставляет что-то вроде схемы для подклассов. Он может быть частично реализован тем, что он содержит полностью определенные конкретные методы, но он также может содержать абстрактные методы. Это методы с сигнатурой, но без тела метода. Любой подкласс должен определять тело для каждого абстрактного метода, в противном случае он также должен быть объявлен абстрактным. Поскольку абстрактные классы не могут быть созданы, они должны быть расширены как минимум на один подкласс, чтобы их можно было использовать. Думайте об абстрактном классе как об общем классе, и подклассы должны заполнить недостающую информацию.

Класс, который может иметь как конкретные, так и не конкретные методы, т.е. с телом и без.

  1. Методы без реализации должны содержать ключевое слово abstract.
  2. Абстрактный класс не может быть создан.

Он ничего не делает, просто предоставляет общий шаблон, который будет использоваться для его подкласса.

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