Che cos'è una "classe astratta" in Java?
Che cos'è una "classe astratta" in Java?
Risposte:
Una classe astratta è una classe che non può essere istanziata. Una classe astratta viene utilizzata creando una sottoclasse ereditaria che può essere istanziata. Una classe astratta fa alcune cose per la sottoclasse ereditaria:
Ecco un esempio:
abstract public class AbstractClass
{
abstract public void abstractMethod();
public void implementedMethod() { System.out.print("implementedMethod()"); }
final public void finalMethod() { System.out.print("finalMethod()"); }
}
Si noti che "abstractMethod ()" non ha alcun metodo body. Per questo motivo, non è possibile effettuare le seguenti operazioni:
public class ImplementingClass extends AbstractClass
{
// ERROR!
}
Non esiste un metodo che attui abstractMethod()
! Quindi non c'è modo per la JVM di sapere cosa dovrebbe fare quando ottiene qualcosa di simile new ImplementingClass().abstractMethod()
.
Ecco un corretto ImplementingClass
.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
}
Si noti che non è necessario definire implementedMethod()
o finalMethod()
. Sono già stati definiti da AbstractClass
.
Ecco un altro corretto ImplementingClass
.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
In questo caso, hai ignorato implementedMethod()
.
Tuttavia, a causa della final
parola chiave, non è possibile quanto segue.
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!"); }
}
Non puoi farlo perché l'implementazione di finalMethod()
in AbstractClass
è contrassegnata come l'implementazione finale di finalMethod()
: nessun'altra implementazione sarà consentita, mai.
Ora puoi anche implementare una classe astratta due volte:
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()"); }
}
Ora da qualche parte potresti scrivere un altro metodo.
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()"
}
Si noti che anche se abbiamo dichiarato b
un AbstractClass
tipo, viene visualizzato "Overriden!"
. Questo perché l'oggetto che abbiamo istanziato era in realtà un ImplementingClass
, il cui implementedMethod()
ovviamente è ignorato. (Potresti aver visto questo indicato come polimorfismo.)
Se desideriamo accedere a un membro specifico di una particolare sottoclasse, dobbiamo prima eseguire il cast di quella sottoclasse:
// 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();
Infine, non puoi fare quanto segue:
public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
... // implementation
}
È possibile estendere una sola classe alla volta. Se è necessario estendere più classi, devono essere interfacce. Puoi farlo:
public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
... // implementation
}
Ecco un'interfaccia di esempio:
interface InterfaceA
{
void interfaceMethod();
}
Questo è fondamentalmente lo stesso di:
abstract public class InterfaceA
{
abstract public void interfaceMethod();
}
L'unica differenza è che il secondo modo non fa sapere al compilatore che in realtà è un'interfaccia. Questo può essere utile se vuoi che le persone implementino solo la tua interfaccia e nessun altro. Tuttavia, come regola generale per principianti, se la tua classe astratta ha solo metodi astratti, probabilmente dovresti renderla un'interfaccia.
Quanto segue è illegale:
interface InterfaceB
{
void interfaceMethod() { System.out.print("ERROR!"); }
}
Non è possibile implementare metodi in un'interfaccia. Ciò significa che se si implementano due interfacce diverse, i diversi metodi in quelle interfacce non possono scontrarsi. Poiché tutti i metodi in un'interfaccia sono astratti, è necessario implementare il metodo e poiché il metodo è l'unica implementazione nella struttura ereditaria, il compilatore sa che deve utilizzare il metodo.
c.implementedMethod()
stampare "Overriden!"? SecondImplementingClass
non sostituisce implementedMethod()
.
Una classe Java diventa astratta nelle seguenti condizioni:
1. Almeno uno dei metodi è contrassegnato come astratto:
public abstract void myMethod()
In tal caso il compilatore ti obbliga a contrassegnare l'intera classe come astratta.
2. La classe è contrassegnata come astratta:
abstract class MyClass
Come già detto: se hai un metodo astratto, il compilatore ti costringe a contrassegnare l'intera classe come astratta. Ma anche se non hai alcun metodo astratto, puoi comunque contrassegnare la classe come astratta.
Uso comune:
Un uso comune di classi astratte è quello di fornire una struttura simile a quella di un'interfaccia. A differenza di un'interfaccia, può già fornire funzionalità, ovvero alcune parti della classe sono implementate e alcune parti sono appena delineate con una dichiarazione del metodo. ("astratto")
Non è possibile creare un'istanza di una classe astratta, ma è possibile creare una classe concreta basata su una classe astratta, che può quindi essere istanziata. Per fare ciò devi ereditare dalla classe astratta e sovrascrivere i metodi astratti, cioè implementarli.
abstract
parola chiave è tutto ciò che è necessario affinché una classe sia astratta. Ma una classe concreta non può contenere un abstract
metodo . Pertanto, se la tua classe ha un abstract
metodo, deve essere dichiarata come abstract
classe al compilatore.
Una classe dichiarata utilizzando la parola chiave astratta è nota come abstract class
. L'astrazione è un processo per nascondere i dettagli di implementazione dei dati e mostrare all'utente solo funzionalità. L'astrazione ti consente di concentrarti su ciò che fa l'oggetto anziché su come lo fa.
Principali cose di classe astratta
Una classe astratta può contenere o meno metodi astratti. Possono esserci metodi non astratti.
Un metodo astratto è un metodo dichiarato senza implementazione (senza parentesi graffe e seguito da un punto e virgola), come questo:
es: abstract void moveTo(double deltaX, double deltaY);
Se una classe ha almeno un metodo astratto, quella classe deve essere astratta
Le classi astratte non possono essere istanziate (non è consentito creare oggetti di classe astratta)
Per usare una classe astratta, devi ereditarla da un'altra classe. Fornire implementazioni a tutti i metodi astratti in esso.
Se erediti una classe astratta, devi fornire implementazioni a tutti i metodi astratti in essa contenuti.
Dichiara classe astratta La
specifica della abstract
parola chiave prima della classe durante la dichiarazione la rende astratta. Dai un'occhiata al codice qui sotto:
abstract class AbstractDemo{ }
Dichiara metodo astratto La
specifica della abstract
parola chiave prima del metodo durante la dichiarazione la rende astratta. Dai un'occhiata al codice qui sotto,
abstract void moveTo();//no body
Perché abbiamo bisogno di astrarre le classi
In un'applicazione di disegno orientata agli oggetti, puoi disegnare cerchi, rettangoli, linee, curve di Bezier e molti altri oggetti grafici. Tutti questi oggetti hanno determinati stati (ad es.: Posizione, orientamento, colore della linea, colore di riempimento) e comportamenti (ad es.: Spostare, ruotare, ridimensionare, disegnare) in comune. Alcuni di questi stati e comportamenti sono gli stessi per tutti gli oggetti grafici (ad esempio: colore di riempimento, posizione e spostamento). Altri richiedono un'implementazione diversa (ad esempio: ridimensionare o disegnare). Tutti gli oggetti grafici devono essere in grado di disegnare o ridimensionare se stessi, differiscono solo nel modo in cui lo fanno.
Questa è una situazione perfetta per una superclasse astratta. È possibile sfruttare le somiglianze e dichiarare che tutti gli oggetti grafici ereditano dallo stesso oggetto padre astratto (per GraphicObject
esempio:) come mostrato nella figura seguente.
Innanzitutto, si dichiara una classe astratta GraphicObject
, per fornire variabili e metodi membri che sono interamente condivisi da tutte le sottoclassi, come la posizione corrente e il metodo moveTo. GraphicObject
ha anche dichiarato metodi astratti, come disegnare o ridimensionare, che devono essere implementati da tutte le sottoclassi ma devono essere implementati in modi diversi. La GraphicObject
classe può assomigliare a questa:
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();
}
Uso del metodo astratto in sottoclassi
Ogni sottoclasse non astratta di GraphicObject
, come Circle
e Rectangle
, deve fornire implementazioni per i metodi draw
e 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
}
}
All'interno del main
metodo è possibile chiamare tutti i metodi in questo modo:
public static void main(String args[]){
GraphicObject c = new Circle();
c.draw();
c.resize();
c.moveTo(4,5);
}
Modi per raggiungere l'astrazione in Java
Esistono due modi per ottenere l'astrazione in Java
Classe astratta con costruttori, membri di dati, metodi, ecc
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);
}
}
Produzione:
GraphicObject is created
Draw the Circle
Change position according to 6 and 4
Ricorda due regole:
Se la classe ha pochi metodi astratti e pochi metodi concreti, dichiarala come abstract
classe.
Se la classe ha solo metodi astratti, dichiarala come interface
.
Riferimenti:
È una classe che non può essere istanziata e forza l'implementazione di classi per, possibilmente, implementare metodi astratti che delinea.
In parole semplici, puoi pensare a una classe astratta come a un'interfaccia con un po 'più di funzionalità.
Non è possibile creare un'istanza di un'interfaccia, che vale anche per una classe astratta.
Sulla tua interfaccia puoi semplicemente definire le intestazioni del metodo e TUTTI gli implementatori sono costretti a implementarle tutte . Su una classe astratta puoi anche definire le intestazioni del tuo metodo ma qui, con la differenza dell'interfaccia, puoi anche definire il corpo (di solito un'implementazione predefinita) del metodo. Inoltre, quando altre classi estendono (nota, non implementano e quindi puoi avere solo una classe astratta per classe figlio) la tua classe astratta, non sono costretti a implementare tutti i tuoi metodi della tua classe astratta, a meno che tu non abbia specificato un metodo astratto ( in tal caso funziona come per le interfacce, non è possibile definire il corpo del metodo).
public abstract class MyAbstractClass{
public abstract void DoSomething();
}
Altrimenti per i normali metodi di una classe astratta, gli "ereditari" possono semplicemente usare il comportamento predefinito o sovrascriverlo, come al solito.
Esempio:
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();
}
Dalla documentazione di Oracle
Metodi e classi astratti:
Una classe astratta è una classe dichiarata astratta, che può o meno includere metodi astratti
Le classi astratte non possono essere istanziate, ma possono essere sottoclassate
Un metodo astratto è un metodo dichiarato senza implementazione (senza parentesi graffe e seguito da un punto e virgola), in questo modo:
abstract void moveTo(double deltaX, double deltaY);
Se una classe include metodi astratti, la classe stessa deve essere dichiarata astratta, come in:
public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}
Quando una classe astratta viene sottoclassata, la sottoclasse di solito fornisce implementazioni per tutti i metodi astratti nella sua classe genitore. Tuttavia, in caso contrario, anche la sottoclasse deve essere dichiarata astratta .
Poiché abstract classes
e interfaces
sono correlati, dai un'occhiata alle domande SE seguenti:
Qual è la differenza tra un'interfaccia e una classe astratta?
Come avrei dovuto spiegare la differenza tra un'interfaccia e una classe astratta?
Ottieni le tue risposte qui:
Classe astratta vs interfaccia in Java
Una classe astratta può avere un metodo finale?
A proposito, queste sono le domande che hai posto di recente. Pensa a una nuova domanda per costruire la reputazione ...
Modificare:
Appena realizzato, che i poster di questo e le domande di riferimento hanno lo stesso nome o almeno simile, ma l'ID utente è sempre diverso. Quindi, c'è anche un problema tecnico, che keyur ha problemi ad accedere di nuovo e a trovare le risposte alle sue domande o questa è una sorta di gioco per intrattenere la comunità SO;)
Piccola aggiunta a tutti questi post.
A volte potresti voler dichiarare una classe e tuttavia non sapere come definire tutti i metodi che appartengono a quella classe. Ad esempio, potresti voler dichiarare una classe chiamata Writer e includere in essa un metodo membro chiamato write () . Tuttavia, non sai come scrivere il codice () perché è diverso per ogni tipo di dispositivo Writer. Naturalmente, prevedi di gestirlo derivando una sottoclasse di Writer, come Stampante, Disco, Rete e Console.
Una classe astratta non può essere istanziata direttamente, ma deve essere derivata per essere utilizzabile. Una classe DEVE essere astratta se contiene metodi astratti: direttamente
abstract class Foo {
abstract void someMethod();
}
o indirettamente
interface IFoo {
void someMethod();
}
abstract class Foo2 implements IFoo {
}
Tuttavia, una classe può essere astratta senza contenere metodi astratti. È un modo per prevenire l'istanza diretta, ad es
abstract class Foo3 {
}
class Bar extends Foo3 {
}
Foo3 myVar = new Foo3(); // illegal! class is abstract
Foo3 myVar = new Bar(); // allowed!
Quest'ultimo stile di classi astratte può essere usato per creare classi "simili a interfacce". A differenza delle interfacce, una classe astratta può contenere metodi non astratti e variabili di istanza. Puoi usarlo per fornire alcune funzionalità di base per estendere le classi.
Un altro modello frequente è l'implementazione della funzionalità principale nella classe astratta e la definizione di parte dell'algoritmo in un metodo astratto che deve essere implementato da una classe estesa. Stupido esempio:
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();
}
Una classe astratta è una classe dichiarata astratta - può o meno includere metodi astratti. Le classi astratte non possono essere istanziate, ma possono essere sottoclassate.
In altre parole, una classe dichiarata con una parola chiave astratta, è conosciuta come classe astratta in java. Può avere metodi astratti (metodo senza corpo) e metodi non astratti (metodo con corpo).
Nota importante: - Le classi astratte non possono essere utilizzate per creare un'istanza di oggetti, ma possono essere utilizzate per creare riferimenti a oggetti, poiché l'approccio di Java al polimorfismo di runtime viene implementato mediante l'uso di riferimenti di superclasse. Pertanto, deve essere possibile creare un riferimento a una classe astratta in modo che possa essere utilizzato per puntare a un oggetto di sottoclasse. Vedrai questa funzione nell'esempio seguente
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();
}
}
Una classe astratta è una classe che non è completamente implementata ma fornisce una sorta di progetto per le sottoclassi. Può essere parzialmente implementato in quanto contiene metodi concreti completamente definiti, ma può anche contenere metodi astratti. Questi sono metodi con una firma ma nessun corpo del metodo. Qualsiasi sottoclasse deve definire un corpo per ciascun metodo astratto, altrimenti deve essere dichiarato astratto. Poiché le classi astratte non possono essere istanziate, per essere utilizzate devono essere estese di almeno una sottoclasse. Pensa alla classe astratta come alla classe generica e le sottoclassi sono lì per riempire le informazioni mancanti.
Non fa nulla, basta fornire un modello comune che verrà condiviso per la sua sottoclasse