J'ai précédemment appris que la classe abstraite peut étendre la classe concrète. Bien que les concepteurs de Java n’en voient pas la raison, mais c’est correct… j’ai aussi appris qu’une classe abstraite qui étend une classe concrète peut rendre abstraites les méthodes remplacées. Pourquoi? Pouvez-vous fournir un cas d'utilisation utile? J'essaie d'apprendre des modèles de design et je ne veux rien rater.
Voici un exemple:
public class Foo
{
public void test()
{
}
}
public abstract class Bar extends Foo
{
@Override
public abstract void test();
}
Cela devient utile si j’ai un ensemble de classes pour lequel je veux une implémentation par défaut de test()
(elles peuvent donc s’étendre de Foo
), ainsi qu’un sous-ensemble de ces classes que je veux forcer à fournir leur propre implémentation (auquel cas le faire résumé dans la sous-classe l’appliquerait.)
Bien sûr, la solution alternative dans cet exemple serait de déclarer test()
abstract dans la classe de niveau supérieur plutôt que dans la sous-classe, et c'est ce que vous feriez habituellement - mais il existe des cas où satisfaire à une relation d'héritage signifie que de temps en temps, cela fait plus de sens du point de vue de la conception. C'est rare, mais vous le voyez parfois.
En passant, même s’il s’agit d’un cas spécial, rappelez-vous que toutes les classes étendent implicitement Object
, sauf indication contraire. Donc, si vous incluez ce cas, les classes abstraites prolongeant des classes concrètes ne sont pas si inhabituelles après tout!
Il s'agit essentiellement de réutiliser de manière sélective du code existant (existant?).
Par exemple : Supposons que quelqu'un ait déjà créé un concret-classe-C (bien sûr, l'implémentation complète).
Maintenant, puisque vous concevez un nouveau système (qui a unabstract class-A), vous avez analysé le système existant et découvert que vous allez avoir des méthodes presque similaires à celles de béton-classe-C . Mais vous avez également constaté que certaines méthodes de la classe concrète-C sont trop spécifiques et que vous souhaitez imposer l’implémentation de ces méthodes dans les sous-classes concrètes de laabstract class-A.
Ainsi, il vous permet de choisir de manière sélective les méthodes à réutiliser et celles à ne pas réutiliser.
Pour que la classe qui a étendu votre classe (rendue abstraite) fournisse un type spécifique d'implémentation.
Par exemple:
Cette flexibilité est particulièrement utile lorsqu'un système évolue et que nous ne voulons pas perturber le code existant.
Un exemple simple auquel je pourrais penser est celui d’une classe MSDocReader. Cette classe fait partie de l'ancien système et de nombreuses autres applications en dépendent.
Maintenant, les exigences changent. Nous devons écrire des classes pour lire des fichiers docx, ppt et même des fichiers xsl.
La classe MSDocReader contient des méthodes qui peuvent être réutilisées, telles que l’obtention de la taille du fichier en KB, en se connectant au framework .Net (si je ne me trompe pas :-))
Maintenant, en utilisant cette disposition, nous pouvons écrire une classe absolue AbstractMSFileReader qui contiendra toutes les méthodes utilisées dans MSDocReader. Mais cette classe aura la méthode de lecture en tant que résumé.
La raison en est que nous voulons forcer les développeurs à utiliser leur propre version de la méthode de lecture. (Nous ne devrions pas utiliser l'héritage, car l'héritage indique clairement que la méthode Subclass étendra les fonctionnalités de la méthode parent. La lecture d'un fichier doc et la lecture d'un fichier Excel sont deux choses différentes et ne relèvent pas du même hiérarchie .)
Et vous pouvez soutenir que nous pouvons créer une classe abstraite et faire en sorte que la classe MSDocReader étende cette classe abstraite. Mais il peut arriver que la classe MSDocReader puisse étendre une autre classe et que Java ne supporte pas l'héritage multiple. Cela peut créer des problèmes
Si vous créez l'abstraction de la méthode test
, les utilisateurs de la classe Bar
seront forcés de fournir une implémentation de la méthode.
Si vous supprimez la méthode abstraite de la classe Bar
, toute personne dérivant de Bar
n'aura pas n'a - pas pour implémenter la méthode test
car Foo
fournit déjà une implémentation (vide).