Supposons que nous ayons ce problème
public class Father{ public void method1(){...} } public class Child1 extends Father{ public void method1() throws Exception{ super.method1(); ... } }
Child1
étend Father
et remplace method1
mais étant donné l’implémentation, Child1.method1
lève maintenant une exception. Cela ne comstackra pas car la méthode de substitution ne peut pas générer de nouvelles exceptions.
Quelle est la meilleure solution?
Father
. Pour moi, cela va à l’encontre de l’encapsulation, de l’inheritance et de la POO générale (le Father
lève potentiellement une exception qui ne se produira jamais). RuntimeException
? Cette solution ne propage pas l’ Exception
au Father
, mais la documentation Oracle et d’autres sources indiquent que la classe des exceptions doit être utilisée lorsque “le code client ne peut rien faire”. Ce n’est pas ce cas, cette exception sera utile pour récupérer blablabla (pourquoi est-il erroné d’utiliser RuntimeException
place?). Utiliser RTE n’est pas une mauvaise idée. Ceci est la méthodologie du framework Spring et cela fonctionne assez bien. Si vous implémentez une application, utilisez probablement cette solution.
Si toutefois vous implémentez une bibliothèque qui expose l’API IMHO, vous devez utiliser une exception vérifiée. Dans ce cas, vous devez créer votre propre exception, par exemple BaseException
. La méthode method()
de Father
lancera. ChildException extends BaseException
et declare method1()
de la classe enfant pour la lancer.
Cela ne rompt pas l’encapsulation: la classe de base lève une exception de base. Il n’a aucune idée de l’exception concrète. La classe enfant lève une exception concrète qui étend toutefois l’exception de base et peut donc être traitée par le code client comme une exception de base.
À titre d’exemple, je peux vous donner IOException
et FileNotFoundException
qui l’étend. Vous pouvez FileInputStream
un stream d’entrée capturant une IOException
lorsque le stream concret est FileInputStream
et qu’il lève une FileNotFoundException
. Mais le client ne le sait pas. Il attrape IOException
.
Si la méthode super class ne déclare pas une exception, la méthode substituée par la sous-classe ne peut pas déclarer une exception vérifiée . Donc, vous ne pouvez utiliser qu’une exception non contrôlée.
Une autre option consiste à autoriser la classe Super à déclarer une ParentException
, puis les méthodes substituées par un enfant peuvent déclarer toutes les exceptions qui sont des enfants de la ParentException
Dépend de ce qui lève l’exception dans Child1. Si ses conditions préalables, etc., vous pouvez toujours utiliser l’une des sous-classes de RuntimeException telle que IllegalArgumentException.
Cependant, s’il existe une sorte d’exception CheckedException, la logique vous suggère de gérer cette méthode elle-même et d’afficher le message d’une autre manière.
Je pense que la règle générale est que
si vous savez comment vous en occuper .. utilisez une exception vérifiée, exception non vérifiée
La partie “jette” fait partie de la signature de la méthode.
C’est pourquoi la méthode de la classe “enfant” n’est pas une substitution de la méthode de la classe parente.
Propager l’exception requirejse au père .. pour moi, cela va à l’encontre de l’encapsulation, de l’inheritance et de la POO générale (le père peut potentiellement lancer une exception qui ne se produira jamais)
Au contraire: c’est bon OO. Image du côté de l’appelant:
Father f = factory.getSomeImplementation(); f.method1(); // user has no chance to see the `Exception` of Child coming...
L’usine peut renvoyer une instance de Father
ou Child
ou quelque chose de complètement différent comme Brother
. Mais le contrat de method1
doit être le même dans tous les cas. Et ce contrat comprend des exceptions vérifiées. C’est le principe de substitution de Liskov, l’une des règles de base de OO.
Ainsi, si l’exception fait partie du contrat commercial de method1
elle doit être déclarée à la racine. Si ce n’est pas le cas (par exemple, une vérification d’argument simple), une RuntimeException
est la route à suivre de toute façon (c’est-à-dire même sans inheritance).