Що таке "абстрактний клас" на 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()
в 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 class AbstractDemo{ }
Оголосити абстрактний метод
Зазначення abstract
ключового слова перед методом під час декларування робить його абстрактним. Подивіться на код нижче,
abstract void moveTo();//no body
Чому нам потрібні абстрактні заняття
У об’єктно-орієнтованому додатку для малювання можна малювати кола, прямокутники, лінії, криві Безьє та багато інших графічних об’єктів. Усі ці об'єкти мають спільні певні стани (наприклад, положення, орієнтація, колір лінії, колір заливки) та поведінку (наприклад, для переміщення, переміщення, зміни розміру, малювання). Деякі з цих станів і поведінки однакові для всіх графічних об'єктів (наприклад, колір заповнення, положення та переміщенняTo). Для інших потрібна інша реалізація (наприклад, розмір чи малюнок). Усі графічні об’єкти повинні вміти малювати чи змінювати розміри, вони просто відрізняються тим, як це роблять.
Це ідеальна ситуація для абстрактного суперкласу. Ви можете скористатися подібністю та оголосити всі графічні об'єкти успадкованими від того самого абстрактного батьківського об'єкта (наприклад:), 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
Є два способи досягти абстракції в яві
Абстрактний клас з конструкторами, членами даних, методами тощо
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();
}
З документації oracle
Абстрактні методи та заняття:
Абстрактний клас - це клас, який оголошується абстрактним - він може включати або не включати абстрактні методи
Абстрактні класи не можуть бути екземплярами, але вони можуть бути підкласами
Абстрактний метод - це метод, який оголошується без реалізації (без дужок і слідує крапкою з комою), наприклад:
abstract void moveTo(double deltaX, double deltaY);
Якщо клас включає абстрактні методи, то сам клас повинен бути оголошений абстрактним, як у:
public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}
Коли абстрактний клас є підкласом, підклас зазвичай забезпечує реалізацію для всіх абстрактних методів у своєму батьківському класі. Однак якщо цього немає, підклас також повинен бути оголошений абстрактним .
Оскільки abstract classes
і interfaces
пов'язані між собою, дивіться нижче питання SE:
Чим відрізняється інтерфейс від абстрактного класу?
Як я повинен пояснити різницю між класом інтерфейсу та абстрактним?
Отримайте відповіді тут:
Абстрактний клас проти інтерфейсу на Java
Чи може абстрактний клас мати остаточний метод?
BTW - це питання, які ви задали нещодавно. Подумайте над новим питанням для формування репутації ...
Редагувати:
Щойно зрозумів, що афіші цього та посилань на них мають однакове або принаймні подібне ім'я, але ідентифікатор користувача завжди відрізняється. Отже, або є технічна проблема, що у клавіатури виникають проблеми з входом знову і пошуку відповідей на його запитання, або це якась гра для розваги спільноти SO;)
Невелике доповнення до всіх цих постів.
Іноді ви можете оголосити клас, але ще не знаєте, як визначити всі методи, що належать до цього класу. Наприклад, ви можете оголосити клас під назвою Writer і включити до нього метод-член, який називається write () . Однак ви не знаєте, як кодувати write (), оскільки це різне для кожного типу пристроїв Writer. Звичайно, ви плануєте це впоратися, вивівши підклас програми 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();
}
}
Абстрактний клас - це той, який не повністю реалізований, але забезпечує щось підґрунтя для підкласів. Це може бути частково реалізовано тим, що воно містить повністю визначені конкретні методи, але воно може також містити абстрактні методи. Це методи з підписом, але немає методу. Будь-який підклас повинен визначати тіло для кожного абстрактного методу, інакше він також повинен бути оголошений абстрактним. Оскільки абстрактні класи не можуть бути ініціативними, їх слід подовжити хоча б одним підкласом, щоб їх використовувати. Подумайте про абстрактний клас як про загальний клас, а підкласи є там, щоб заповнити відсутні дані.
Це нічого не робить, просто надайте загальний шаблон, яким буде надано спільний доступ до його підкласу