Qu'est-ce qu'une "classe abstraite" en Java?
Qu'est-ce qu'une "classe abstraite" en Java?
Réponses:
Une classe abstraite est une classe qui ne peut pas être instanciée. Une classe abstraite est utilisée en créant une sous-classe héritée qui peut être instanciée. Une classe abstraite fait quelques choses pour la sous-classe héritée:
Voici un exemple:
abstract public class AbstractClass
{
abstract public void abstractMethod();
public void implementedMethod() { System.out.print("implementedMethod()"); }
final public void finalMethod() { System.out.print("finalMethod()"); }
}
Notez que "abstractMethod ()" n'a pas de corps de méthode. Pour cette raison, vous ne pouvez pas effectuer les opérations suivantes:
public class ImplementingClass extends AbstractClass
{
// ERROR!
}
Il n'y a aucune méthode qui implémente abstractMethod()
! Il n'y a donc aucun moyen pour la JVM de savoir ce qu'elle est censée faire lorsqu'elle obtient quelque chose new ImplementingClass().abstractMethod()
.
Voici une bonne réponse ImplementingClass
.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
}
Notez que vous n'avez pas besoin de définir implementedMethod()
ou finalMethod()
. Ils étaient déjà définis par AbstractClass
.
Voici un autre correct ImplementingClass
.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
Dans ce cas, vous avez remplacé implementedMethod()
.
Cependant, en raison du final
mot - clé, ce qui suit n'est pas possible.
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!"); }
}
Vous ne pouvez pas faire cela car l'implémentation de finalMethod()
in AbstractClass
est marquée comme implémentation finale de finalMethod()
: aucune autre implémentation ne sera autorisée, jamais.
Maintenant, vous pouvez également implémenter une classe abstraite deux fois:
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()"); }
}
Maintenant, quelque part, vous pourriez écrire une autre méthode.
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()"
}
Notez que même si nous avons déclaré b
un AbstractClass
type, il s'affiche "Overriden!"
. C'est parce que l'objet que nous avons instancié était en fait un ImplementingClass
, dont il implementedMethod()
est bien sûr remplacé. (Vous avez peut-être vu ce phénomène sous le nom de polymorphisme.)
Si nous souhaitons accéder à un membre spécifique à une sous-classe particulière, nous devons d'abord effectuer une descente dans cette sous-classe:
// 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();
Enfin, vous ne pouvez pas effectuer les opérations suivantes:
public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
... // implementation
}
Une seule classe peut être prolongée à la fois. Si vous devez étendre plusieurs classes, elles doivent être des interfaces. Tu peux le faire:
public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
... // implementation
}
Voici un exemple d'interface:
interface InterfaceA
{
void interfaceMethod();
}
C'est essentiellement la même chose que:
abstract public class InterfaceA
{
abstract public void interfaceMethod();
}
La seule différence est que la deuxième façon ne permet pas au compilateur de savoir qu'il s'agit en fait d'une interface. Cela peut être utile si vous voulez que les gens implémentent uniquement votre interface et aucune autre. Cependant, en règle générale, si votre classe abstraite n'a que des méthodes abstraites, vous devriez probablement en faire une interface.
Ce qui suit est illégal:
interface InterfaceB
{
void interfaceMethod() { System.out.print("ERROR!"); }
}
Vous ne pouvez pas implémenter de méthodes dans une interface. Cela signifie que si vous implémentez deux interfaces différentes, les différentes méthodes de ces interfaces ne peuvent pas entrer en collision. Comme toutes les méthodes d'une interface sont abstraites, vous devez implémenter la méthode, et puisque votre méthode est la seule implémentation dans l'arbre d'héritage, le compilateur sait qu'il doit utiliser votre méthode.
c.implementedMethod()
imprimerait "Overriden!"? SecondImplementingClass
ne remplace pas implementedMethod()
.
Une classe Java devient abstraite dans les conditions suivantes:
1. Au moins une des méthodes est marquée comme abstraite:
public abstract void myMethod()
Dans ce cas, le compilateur vous oblige à marquer toute la classe comme abstraite.
2. La classe est marquée comme abstraite:
abstract class MyClass
Comme déjà dit: si vous avez une méthode abstraite, le compilateur vous oblige à marquer toute la classe comme abstraite. Mais même si vous n'avez pas de méthode abstraite, vous pouvez toujours marquer la classe comme abstraite.
Usage commun:
Une utilisation courante des classes abstraites est de fournir un aperçu d'une classe similaire à celle d'une interface. Mais contrairement à une interface, elle peut déjà fournir des fonctionnalités, c'est-à-dire que certaines parties de la classe sont implémentées et certaines parties sont simplement décrites avec une déclaration de méthode. ("abstrait")
Une classe abstraite ne peut pas être instanciée, mais vous pouvez créer une classe concrète basée sur une classe abstraite, qui peut ensuite être instanciée. Pour ce faire, vous devez hériter de la classe abstraite et remplacer les méthodes abstraites, c'est-à-dire les implémenter.
abstract
mot - clé est tout ce qui est nécessaire pour qu'une classe soit abstraite. Mais une classe concrète ne peut pas contenir de abstract
méthode . Ainsi, si votre classe a une abstract
méthode, elle doit être déclarée en tant que abstract
classe au compilateur.
Une classe déclarée à l'aide du mot clé abstract est connue sous le nom de abstract class
. L'abstraction est un processus consistant à masquer les détails d'implémentation des données et à n'afficher que les fonctionnalités pour l'utilisateur. L'abstraction vous permet de vous concentrer sur ce que fait l'objet au lieu de le faire.
Principales choses de la classe abstraite
Une classe abstraite peut contenir ou non des méthodes abstraites. Il peut y avoir des méthodes non abstraites.
Une méthode abstraite est une méthode qui est déclarée sans implémentation (sans accolades et suivie d'un point-virgule), comme ceci:
ex: abstract void moveTo(double deltaX, double deltaY);
Si une classe a au moins une méthode abstraite, alors cette classe doit être abstraite
Les classes abstraites ne peuvent pas être instanciées (vous n'êtes pas autorisé à créer un objet de classe abstraite)
Pour utiliser une classe abstraite, vous devez l'hériter d'une autre classe. Fournissez des implémentations à toutes les méthodes abstraites qu'il contient.
Si vous héritez d'une classe abstraite, vous devez fournir des implémentations à toutes les méthodes abstraites qu'elle contient.
Déclarez la classe abstraite
La spécification du abstract
mot-clé avant la classe lors de la déclaration le rend abstrait. Jetez un œil au code ci-dessous:
abstract class AbstractDemo{ }
Déclarer la méthode abstraite
La spécification du abstract
mot-clé avant la méthode lors de la déclaration la rend abstraite. Jetez un œil au code ci-dessous,
abstract void moveTo();//no body
Pourquoi nous avons besoin d'abstraire des classes
Dans une application de dessin orientée objet, vous pouvez dessiner des cercles, des rectangles, des lignes, des courbes de Bézier et de nombreux autres objets graphiques. Ces objets ont tous certains états (pour ex -: position, orientation, couleur de trait, couleur de remplissage) et des comportements (pour ex -: moveTo, rotation, redimensionnement, dessin) en commun. Certains de ces états et comportements sont les mêmes pour tous les objets graphiques (par exemple: couleur de remplissage, position et moveTo). D'autres nécessitent une implémentation différente (par exemple: redimensionner ou dessiner). Tous les objets graphiques doivent pouvoir se dessiner ou se redimensionner, ils diffèrent simplement par la façon dont ils le font.
C'est une situation parfaite pour une superclasse abstraite. Vous pouvez tirer parti des similitudes et déclarer tous les objets graphiques à hériter du même objet parent abstrait (par exemple:) GraphicObject
comme indiqué dans la figure suivante.
Tout d'abord, vous déclarez une classe abstraite GraphicObject
, pour fournir des variables et des méthodes membres qui sont entièrement partagées par toutes les sous-classes, telles que la position actuelle et la méthode moveTo. GraphicObject
ont également déclaré des méthodes abstraites, telles que draw ou resize, qui doivent être implémentées par toutes les sous-classes mais doivent être implémentées de différentes manières. La GraphicObject
classe peut ressembler à ceci:
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();
}
Utilisation de la méthode abstraite dans les sous-classes
Chaque sous-classe non abstraite de GraphicObject
, comme Circle
et Rectangle
, doit fournir des implémentations pour les méthodes draw
et 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
}
}
Dans la main
méthode, vous pouvez appeler toutes les méthodes comme ceci:
public static void main(String args[]){
GraphicObject c = new Circle();
c.draw();
c.resize();
c.moveTo(4,5);
}
Façons d'abstraction en Java
Il existe deux façons de réaliser l'abstraction en Java
Classe abstraite avec constructeurs, membres de données, méthodes, etc.
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);
}
}
Production:
GraphicObject is created
Draw the Circle
Change position according to 6 and 4
Rappelez-vous deux règles:
Si la classe a peu de méthodes abstraites et peu de méthodes concrètes, déclarez-la en tant que abstract
classe.
Si la classe n'a que des méthodes abstraites, déclarez-la en tant que interface
.
Références:
Pour parler simplement, vous pouvez considérer une classe abstraite comme une interface avec un peu plus de capacités.
Vous ne pouvez pas instancier une interface, qui vaut également pour une classe abstraite.
Sur votre interface, vous pouvez simplement définir les en-têtes de méthode et TOUS les implémenteurs sont obligés de les implémenter tous . Sur une classe abstraite, vous pouvez également définir vos en-têtes de méthode mais ici - à la différence de l'interface - vous pouvez également définir le corps (généralement une implémentation par défaut) de la méthode. De plus, lorsque d'autres classes étendent (notez, n'implémentez pas et que vous ne pouvez donc avoir qu'une seule classe abstraite par classe enfant) votre classe abstraite, elles ne sont pas obligées d'implémenter toutes vos méthodes de votre classe abstraite, sauf si vous avez spécifié une méthode abstraite ( dans ce cas, cela fonctionne comme pour les interfaces, vous ne pouvez pas définir le corps de la méthode).
public abstract class MyAbstractClass{
public abstract void DoSomething();
}
Sinon, pour les méthodes normales d'une classe abstraite, les "héritiers" peuvent simplement utiliser le comportement par défaut ou le remplacer, comme d'habitude.
Exemple:
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();
}
Depuis la documentation d' Oracle
Méthodes et classes abstraites:
Une classe abstraite est une classe déclarée abstraite - elle peut ou non inclure des méthodes abstraites
Les classes abstraites ne peuvent pas être instanciées, mais elles peuvent être sous-classées
Une méthode abstraite est une méthode qui est déclarée sans implémentation (sans accolades et suivie d'un point-virgule), comme ceci:
abstract void moveTo(double deltaX, double deltaY);
Si une classe comprend des méthodes abstraites, alors la classe elle-même doit être déclarée abstraite, comme dans:
public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}
Lorsqu'une classe abstraite est sous-classée, la sous-classe fournit généralement des implémentations pour toutes les méthodes abstraites de sa classe parente. Si ce n'est pas le cas, la sous-classe doit également être déclarée abstraite .
Depuis abstract classes
et interfaces
sont liés, jetez un œil aux questions SE ci-dessous:
Quelle est la différence entre une interface et une classe abstraite?
Comment aurais-je dû expliquer la différence entre une interface et une classe abstraite?
Obtenez vos réponses ici:
Classe abstraite vs interface en Java
Une classe abstraite peut-elle avoir une méthode finale?
BTW - ce sont des questions que vous avez posées récemment. Pensez à une nouvelle question pour vous bâtir une réputation ...
Éditer:
Je viens de réaliser que les affiches de cette question et des questions référencées ont le même nom ou au moins un nom similaire, mais l'ID utilisateur est toujours différent. Donc, soit il y a un problème technique, keyur a des problèmes pour se reconnecter et trouver les réponses à ses questions, soit c'est une sorte de jeu pour divertir la communauté SO;)
Petit ajout à tous ces messages.
Parfois, vous souhaiterez peut-être déclarer une classe sans savoir comment définir toutes les méthodes qui appartiennent à cette classe. Par exemple, vous pouvez déclarer une classe appelée Writer et y inclure une méthode membre appelée write () . Cependant, vous ne savez pas comment coder write () car il est différent pour chaque type de périphériques Writer. Bien sûr, vous prévoyez de gérer cela en dérivant une sous-classe de Writer, telle que Imprimante, Disque, Réseau et Console.
Une classe abstraite ne peut pas être directement instanciée, mais doit être dérivée de pour être utilisable. Une classe DOIT être abstraite si elle contient des méthodes abstraites: soit directement
abstract class Foo {
abstract void someMethod();
}
ou indirectement
interface IFoo {
void someMethod();
}
abstract class Foo2 implements IFoo {
}
Cependant, une classe peut être abstraite sans contenir de méthodes abstraites. C'est un moyen d'empêcher l'instanciation directe, par exemple
abstract class Foo3 {
}
class Bar extends Foo3 {
}
Foo3 myVar = new Foo3(); // illegal! class is abstract
Foo3 myVar = new Bar(); // allowed!
Ce dernier style de classes abstraites peut être utilisé pour créer des classes "de type interface". Contrairement aux interfaces, une classe abstraite peut contenir des méthodes non abstraites et des variables d'instance. Vous pouvez l'utiliser pour fournir des fonctionnalités de base aux classes d'extension.
Un autre modèle fréquent consiste à implémenter la fonctionnalité principale dans la classe abstraite et à définir une partie de l'algorithme dans une méthode abstraite à implémenter par une classe d'extension. Exemple stupide:
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();
}
Une classe abstraite est une classe déclarée abstraite - elle peut ou non inclure des méthodes abstraites. Les classes abstraites ne peuvent pas être instanciées, mais elles peuvent être sous-classées.
En d'autres termes, une classe déclarée avec un mot-clé abstrait est connue sous le nom de classe abstraite en java. Il peut avoir des méthodes abstraites (méthode sans corps) et non abstraites (méthode avec corps).
Remarque importante: - Les classes abstraites ne peuvent pas être utilisées pour instancier des objets, elles peuvent être utilisées pour créer des références d'objet, car l'approche Java du polymorphisme d'exécution est implémentée à l'aide de références de superclasse. Ainsi, il doit être possible de créer une référence à une classe abstraite afin qu'elle puisse être utilisée pour pointer vers un objet de sous-classe. Vous verrez cette fonctionnalité dans l'exemple ci-dessous
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();
}
}
Une classe abstraite est une classe qui n'est pas entièrement implémentée mais fournit quelque chose d'un modèle pour les sous-classes. Il peut être partiellement implémenté en ce qu'il contient des méthodes concrètes entièrement définies, mais il peut également contenir des méthodes abstraites. Ce sont des méthodes avec une signature mais pas de corps de méthode. Toute sous-classe doit définir un corps pour chaque méthode abstraite, sinon elle doit également être déclarée abstraite. Comme les classes abstraites ne peuvent pas être instanciées, elles doivent être étendues d'au moins une sous-classe pour être utilisées. Considérez la classe abstraite comme la classe générique, et les sous-classes sont là pour remplir les informations manquantes.
Il ne fait rien, il suffit de fournir un modèle commun qui sera partagé pour sa sous-classe