A question about Exception inheritance

W

www

Hi,

I have three classes(Animal, Dog and Cat). For them, I have created
three kinds of Exception class too:

AnimalException, DogException and CatException.

Animal is the superclass of Dog and Cat.

AnimalException, a subclass of Exception, is the superclass of
DogException and CatException.

public class Animal
{

public void doIt() throws AnimalException
{
if(..)
{
throw new AnimalException(getClass().getName() + " screwed up.");
}

}
}


public class Dog extends Animal
{

public void doIt() throws DogException
{
super.doIt(); //oops, wrong!
}
}

The message says that the AnimalException is not handled. I understand
it. So I have to do it:

public class Dog extends Animal
{

public void doIt() throws DogException
{
try
{
super.doIt();
}
catch(AnimalException e)
{
throw new DogException(e.getMessage()); //take the message, re-throw
it again.
}
}
}

I feel this is really pain and un-necessary. Since I run into such
patterns many times, I am wondering if anybody could help me out.

Is that wrong to have DogException and CatException? Should I just keep
AnimalException and replace DogException with AnimalException?

Thank you very much.
 
S

Stefan Ram

www said:
public void doIt() throws DogException

Why not »throws AnimalException« here?
Is that wrong to have DogException and CatException?

It is not wrong to have them if they serve a
purpose. But this does not mean that they need
to be used in that throws-clause.
 
M

Mark Rafn

throw new DogException(e.getMessage()); // rethrow

On an unrelated topic, this is NOT rethrowing the exception. This is throwing
a new exception with the same message string. It's generally a bad thing.
You should either
throw e; // rethrow the exception
or
throw new DogException(e); // throw a new message that is chained.

This preserves the stack trace and information in the original exception,
whereas just using e.getMessage() throws it all away.
I have three classes(Animal, Dog and Cat). For them, I have created
three kinds of Exception class too:
AnimalException, DogException and CatException. ....
Is that wrong to have DogException and CatException? Should I just keep
AnimalException and replace DogException with AnimalException?

Maybe - it's complex enough that there's no perfect right and wrong.
Certainly don't create exception types unless they mean something. And
certainly create them if needed. I think your problem is that you're trying
to hide the superclass's AnimalException. Don't - a dog _IS_ an animal, and
it's it's very reasonable for dog.doIt() to throw AnimalException for
exceptions that are common to all animals, and DogException for exceptions
specific to dogs.
 
C

Curt Welch

www said:
Hi,

I have three classes(Animal, Dog and Cat). For them, I have created
three kinds of Exception class too:

AnimalException, DogException and CatException.

Animal is the superclass of Dog and Cat.

AnimalException, a subclass of Exception, is the superclass of
DogException and CatException.

public class Animal
{

public void doIt() throws AnimalException
{
if(..)
{
throw new AnimalException(getClass().getName() +
" screwed up."); }

}
}

public class Dog extends Animal
{

public void doIt() throws DogException
{
super.doIt(); //oops, wrong!
}
}

The message says that the AnimalException is not handled. I understand
it. So I have to do it:

public class Dog extends Animal
{

public void doIt() throws DogException
{
try
{
super.doIt();
}
catch(AnimalException e)
{
throw new DogException(e.getMessage()); //take
the message, re-throw it again.
}
}
}

I feel this is really pain and un-necessary. Since I run into such
patterns many times, I am wondering if anybody could help me out.

Sure. Don't do it. Let Dog throw the Animal exception. It generally makes
no sense to relabel it as a DogException.
Is that wrong to have DogException and CatException? Should I just keep
AnimalException and replace DogException with AnimalException?

Thank you very much.

I'm answering this a month late, so the original poster might not even seen
the answer, and since he didn't use a real email address, I can't CC to
him.

However, the answer is that there is no reason to subclass exceptions to
mirror the classes throwing them. The expectations should instead, mirror
the types of problems that cause them. If the exception is AnimalHitByCar,
then both Dogs and Cats can throw the same exception. It makes no sense to
subclass AnimalHitByCar to create both CatHitByCar and DogHitByCar just
because they are thrown by different classes. If there's only one error
which happens in Animal.doIt(), then there should only be one exception
defined.

Exceptions are defined to report unique error conditions, not unique
sources of the errors. You need a different exception for each type of
error that can cause it to be thrown - unless you think the errors will all
be handled the same way by the catching code - in which case you only need
one exception for all of them: AnimalException.

There are reasons to catch and rethrow Exceptions. You do it so you can
change the implementation of a class without changing it's API. You want
it to throw only one type of error on an exception - like Dog.fetch()
throws DogFailsToFetchException. As you change the code in fetch(), the
other classes you use might throw different exceptions which prevents fetch
from finishing correctly, like "leg() throws BrokenBoneException". But
instead of allowing all the different low level causes of why fetch failed
to propagate update, you just rethrow it (correctly) as a
DogFailesToFecthException with a cause of BrokeBoneException. That way,
the code which uses Dog.fetch() doesn't have to change every time you
change the Dog.fetch() method.
 
R

Roedy Green

It makes no sense to
subclass AnimalHitByCar to create both CatHitByCar and DogHitByCar just
because they are thrown by different classes. If there's only one error
which happens in Animal.doIt(), then there should only be one exception
defined.

Don't bother subclassing exceptions unless you want to HANDLE them
differently. If you just want to pass on additional causal
information, put it in the message or extra Exception fields.
 
D

Daniel Pitts

Roedy said:
Don't bother subclassing exceptions unless you want to HANDLE them
differently. If you just want to pass on additional causal
information, put it in the message or extra Exception fields.
I disagree, subclassing exceptions is good practice, assuming you do the
correct kind of subclassing.

The DogHitByCar/CatHitByCar example is a bad subclassing. Generally,
every "layer" should have its own type of exceptions.

AnimalHitByCarException makes more sense as an exception in this case.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top