Qu'est-ce qu'une "classe abstraite" en Java?
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éréditaire qui can peut être instanciée. Une classe abstraite fait quelques choses pour la sous-classe héréditaire:
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 pas de méthode qui implémente abstractMethod()
! Il n’ya donc aucun moyen pour la JVM de savoir ce qu’elle est censée faire quand elle obtient quelque chose comme new ImplementingClass().abstractMethod()
.
Voici une ImplementingClass
correcte.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
}
Notez qu'il n'est pas nécessaire de définir implementedMethod()
ou finalMethod()
. Ils étaient déjà définis par AbstractClass
.
Voici une autre variable correcte 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()
.
Toutefois, en raison du mot clé final
, les opérations suivantes ne sont pas possibles.
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()
dans AbstractClass
est marquée comme l'implémentation finale de finalMethod()
: aucune autre implémentation ne sera autorisée.
Maintenant, vous pouvez aussi / 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 pouvez é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 type AbstractClass
, il affiche "Overriden!"
. En effet, l'objet que nous avons instancié était en réalité une ImplementingClass
, dont la fonction implementedMethod()
est bien sûr remplacée. (Vous avez peut-être vu ce phénomène appelé polymorphisme.)
Si nous souhaitons accéder à un membre spécifique à une sous-classe particulière, nous devons commencer par descendre 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 faire ce qui suit:
public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
... // implementation
}
Un seul cours peut être prolongé à la fois. Si vous avez besoin d'é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 fondamentalement la même chose que:
abstract public class InterfaceA
{
abstract public void interfaceMethod();
}
La seule différence est que la deuxième méthode ne permet pas au compilateur de savoir qu'il s'agit en réalité d'une interface. Cela peut être utile si vous souhaitez que les utilisateurs n'implémentent que 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 comme votre méthode est la seule implémentation de l'arbre d'héritage, le compilateur sait qu'il doit utiliser votre méthode.
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 la classe entière comme abstraite.
2. La classe est marquée comme étant abstraite:
abstract class MyClass
Comme déjà dit: Si vous avez une méthode abstraite, le compilateur vous oblige à marquer la classe entière 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 consiste à fournir le contour 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 que 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 redéfinir les méthodes abstraites, c'est-à-dire les implémenter.
Une classe déclarée à l'aide du mot clé abstract est appelée abstract class
. L'abstraction consiste à masquer les détails d'implémentation des données et à afficher uniquement les fonctionnalités correspondantes. L'abstraction vous permet de vous concentrer sur ce que fait l'objet au lieu de savoir comment il le fait.
Principaux éléments 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 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, 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. Fournir 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 ses méthodes abstraites.
Declare abstract class Spécifier le mot clé abstract
avant que la classe lors de la déclaration la rende abstraite. Regardez le code ci-dessous:
abstract class AbstractDemo{ }
Declare méthode abstraite Spécifier le mot clé abstract
avant que la méthode en cours de déclaration la rende abstraite. Regardez le code ci-dessous,
abstract void moveTo();//no body
Pourquoi il faut abstraction 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 des états (par exemple: position, orientation, couleur de trait, couleur de remplissage) et des comportements (par exemple: moveTo, faire pivoter, redimensionner, dessiner). Certains de ces états et comportements sont les mêmes pour tous les objets graphiques (par exemple: couleur de remplissage, position et déplacement). D'autres nécessitent une implémentation différente (par exemple: redimensionner ou dessiner). Tous les objets graphiques doivent pouvoir dessiner ou se redimensionner eux-mêmes, ils diffèrent simplement par la manière dont ils le font.
C'est une situation parfaite pour une super-classe abstraite. Vous pouvez tirer parti des similitudes et déclarer que tous les objets graphiques héritent 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
, afin de fournir des variables et méthodes membres entièrement partagées par toutes les sous-classes, telles que la position actuelle et la méthode moveTo. GraphicObject
a également déclaré des méthodes abstraites, telles que dessiner ou redimensionner, qui doivent être implémentées par toutes les sous-classes mais doivent être implémentées de différentes manières. La classe GraphicObject
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
, telle que Circle
et Rectangle
, doit fournir les implémentations des 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 méthode main
, vous pouvez appeler toutes les méthodes telles que:
public static void main(String args[]){
GraphicObject c = new Circle();
c.draw();
c.resize();
c.moveTo(4,5);
}
Moyens de réaliser l'abstraction en Java
Il y a 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);
}
}
Sortie:
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, Le déclare comme une classe abstract
.
Si la classe n'a que des méthodes abstraites, déclarez-la en tant que interface
.
Références:
C'est une classe qui ne peut pas être instanciée et oblige les classes implémentées à éventuellement implémenter des méthodes abstraites qu'elle décrit.
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 bâtir votre réputation ...
Modifier:
Je viens de me rendre compte que les affiches de celle-ci et les questions référencées portent le même nom ou du moins un nom similaire, mais que l'identifiant est toujours différent. Donc, soit, il y a un problème technique, que keyur a des problèmes pour se reconnecter et trouver les réponses à ses questions ou bien c'est une sorte de jeu pour divertir la communauté SO;)
En termes simples, vous pouvez considérer une classe abstraite comme une interface avec un peu plus de fonctionnalités.
Vous ne pouvez pas instancier une interface, qui est également valable 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 forcés pour 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 s’étendent (note, pas implémenter et donc vous pouvez aussi avoir juste une classe abstraite par classe enfant) votre classe abstraite, elles ne sont pas obligées de mettre en œuvre toutes vos méthodes de votre classe abstraite, vous avez spécifié un 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 Oracle documentation
Méthodes et classes abstraites:
Une classe abstraite est une classe déclarée abstraite. Elle peut inclure ou non 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 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 inclut des méthodes abstraites, 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-classe, la sous-classe fournit généralement des implémentations pour toutes les méthodes abstraites de sa classe parente. Toutefois, dans le cas contraire, la sous-classe doit également être déclarée abstraite.
Puisque abstract classes
et interfaces
sont liés, regardez ci-dessous les questions SE:
Quelle est la différence entre une classe d'interface et abstraite?
Comment aurais-je dû expliquer la différence entre une classe d'interface et une classe abstraite?
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();
}
Petit ajout à tous ces posts.
Parfois, vous voudrez peut-être déclarer un classe et pourtant ne sais pas comment définir toutes les méthodes qui appartiennent à cela classe. Par exemple, vous voudrez peut-être déclarer une classe appelée Writer et y inclure une méthode membre appelée écrire() . Cependant, vous ne savez pas comment coder write () car c’est différent pour chaque type d’écrivain dispositifs. Bien sûr, vous envisagez de gérer ceci en dérivant la sous-classe de Writer, tels que Imprimante, Disque, Réseau et Console.
Une classe abstraite ne peut pas être directement instanciée, mais doit en être dérivée pour être utilisable. Une classeDOITê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’instantané direct, 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 est autorisée à contenir des méthodes et des variables d'instance non abstraites. Vous pouvez l'utiliser pour fournir des fonctionnalités de base à l'extension de classes.
Un autre schéma 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 extensible. 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
}
}
Une classe abstraite est une classe qui n'est pas entièrement implémentée mais qui fournit un modèle pour les sous-classes. Il peut être partiellement implémenté en ce sens 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 abstract . Comme les classes abstraites ne peuvent pas être instanciées, elles doivent être étendues d’au moins une sous-classe pour pouvoir être utilisées. Pensez à la classe abstraite en tant que classe générique et les sous-classes sont là pour renseigner les informations manquantes.
Classe pouvant comporter à la fois des méthodes concrètes et non concrètes, c'est-à-dire avec et sans corps.
Une classe abstraite est une classe déclarée abstraite - elle peut inclure ou non 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 appelée 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, mais pour créer des références d'objet, car l'approche de Polymorphism au moment de l'exécution de Java est implémentée via l'utilisation 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 sur 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();
}
}
Il ne fait rien, il suffit de fournir un modèle commun qui sera partagé pour sa sous-classe