deprecating abstract methods

T

Thomas Hawtin

Gabriel said:
How should I correctly declare deprecated an abstract method?

With @deprecated and/or @Deprecated.
The thing is, that if I left the method abstract, I'm forced to
implement it, so the deprecation does not have any effect.

It has effect for clients of the class.

However, deprecation is not inherited. For instance, IIRC, for a long
time Component.show was deprecated but Window.show was not.
But if I remove the abstract clause, I'm changing the method signature,

The deprecated flag is not part of the signature.

Tom Hawtin
 
G

Gabriel Belingueres

Hi,

My question is somewhat trivial and difficult at the same time.

How should I correctly declare deprecated an abstract method?

The thing is, that if I left the method abstract, I'm forced to
implement it, so the deprecation does not have any effect.

But if I remove the abstract clause, I'm changing the method signature,
so I'm deprecating NOT the original method, but something else. Also,
(maybe) different java compiler implementations will not recognize it
as deprecated since I'm overriding the upper class method, so I'm
technically not using the original deprecated method.

Any comments will be welcomed.

Regards,
Gabriel
 
G

Gabriel Belingueres

The thing is, that if I left the method abstract, I'm forced to
It has effect for clients of the class.

Surely. That's whom the @deprecated tag is meant to be.
However, deprecation is not inherited. For instance, IIRC, for a long
time Component.show was deprecated but Window.show was not.

As for JDK 1.4.2, it is not deprecated. This is the root of the problem
and
here I point a difference between what I want to do and what is done in
the
AWT library.
1) It seems to me that in AWT, they wanted that Window.show() not to be
deprecated, or either they forgot to deprecate it because of the
limitations
of the deprecation mechanism.
2) In class Component, the show() method is not abstract.
The deprecated flag is not part of the signature.

It's true, but the abstract keyword in the method signature is.

I think that the actual problem here is that current compilers don't
show a
warning when a subclass override deprecated methods (either abstract or
not)
or implement them (when they are declared in an interface)

I think it would be nice to have such a feature in the compiler...

Gabriel
 
T

Thomas Hawtin

Gabriel said:
Surely. That's whom the @deprecated tag is meant to be.


As for JDK 1.4.2, it is not deprecated. This is the root of the problem
and
here I point a difference between what I want to do and what is done in
the
AWT library.
1) It seems to me that in AWT, they wanted that Window.show() not to be
deprecated, or either they forgot to deprecate it because of the
limitations
of the deprecation mechanism.
2) In class Component, the show() method is not abstract.

In this particular case "they" seem to have been a bit schizophrenic
about what to do about it.

Bug 4090395, "show() is not flagged as deprecated", 03-NOV-1997, Closed,
not a bug.
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4090395

Bug 4689044, "Window.hide() and Window.show() should be deprecated",
21-MAY-2002, Closed, fixed.
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4689044
It's true, but the abstract keyword in the method signature is.

Nor the abstract flag. (Code compiled referencing a class that uses a
non-abstract method but run with an a version that is abstract, will
dynamically link but throw an AbstractMethodError when the method is
called.)

Therefore, you can safely make an abstract method non-abstract.
I think that the actual problem here is that current compilers don't
show a
warning when a subclass override deprecated methods (either abstract or
not)
or implement them (when they are declared in an interface)

I think it would be nice to have such a feature in the compiler...

There are loads of bugs in the Bug Parade related to this. 1.6 currently
does complain. Perhaps there should be a new annotation to state that a
method may override/implement a deprecated method.
@SuppressWarnings("deprecation") works in 1.6, but is heavy-handed as
you don't want it applied to the method body (well, unless it has a
super call).

Tom Hawtin
 
C

Chris Uppal

Gabriel said:
How should I correctly declare deprecated an abstract method?

The thing is, that if I left the method abstract, I'm forced to
implement it, so the deprecation does not have any effect.

I would think about this slightly differently.

A method declared abstract is a promise/requirement that concrete subclasses
will provide it.

If you deprecate it, then what you are doing is removing that /promise/ (or
rather, warning people that the promise /will/ be removed later). You are not
telling sub-class implementers that they mustn't implement a method with that
signature, only that you no longer /require/ them to do so. Nothing whatever
prevents, or should, prevent any subclass implementing such a method -- they
can implement whatever methods they want -- but they should be aware that the
method is no longer part of the semantics provided by the abstract class
(considered as a framework).

Take an example. Say we start with a class Animal:

public abstract class Animal
{
public abstract void makeNoise();
public void die()
{
this.makeNoise();
this. lieStrangelyStill();
this.decompose();
}
//...
}

And subclasses Cat and Dog:

public class Cat
extends Animal
{
public void makeNoise() { this.meaow(); }
public void meaow() { /* ... */ }
//...
}
public class Dog
extends Animal
{
public void makeNoise() { this.woof(); }
public void woof() { /* ... */ }
//...
}

The makeNoise() method is used in two ways. One is that users of Animals can
ask them to make a noise without knowing which /kind/ of animal they have. The
other is the (hopefully documented) fact that Animals make a noise as they die.

Now suppose we realise that animals don't all make noises, think Starfish for
instance. So we decide to deprecate the makeNoise() method in Animal. That
may have two different effects since makeNoise() may be used in two different
ways.

Let's take the effect on users of Animals first. Since that method is
deprecated, they can no longer assume that any random Animal can makeNoise().
But that in no way means that Dogs are suddenly silent! /If/ they know that
they are dealing with a Dog then they can ask it to makeNoise(), just the same
as they can ask it to woof(). Similarly they can ask a Cat to makeNoise() or
meaow(). What has vanished is the connection between the two definitions of
makeNoise() -- they have become independent of each other, and are now
connected only by coincidence of name. But they are both still perfectly valid
methods.

So, in that case, you have removed the promise to users of Animals. As you
say, there is a technical problem that subclasses are still (by Java rules)
required to implement it, even though it is (logically) no longer necessary. A
simple solution is to make it concrete (with an empty body) in the superclass;
that will have no effect on subclasses that already implement that method, but
will not constrain new subclasses.

Now consider the effect on sub-class implementers. This is a completely
different issue. The guarantee that die() will call makeNoise() has gone away.
I don't think that's acceptable except in very tightly coupled (and necessarily
small) code-bases. So you can't do that unless you are willing to change all
the subclasses at the same time -- you have to find a different way to change
the framework that won't break client code. (Arguably, part of the problem
here is that die() called a /public/ method which subclasses were expected to
implement -- a rather fragile design).

So it depends on what you are doing with your abstract methods. In one case
you can deprecate them without problems. In the other, you have to find some
way to avoid deprecating it at all.

-- chris
 
G

Gabriel Belingueres

Hi,

My situation is more like the second you write in your post.

Thanks everyone for your answers.

Since I've done a lot of modifications, I finally decided to change the
framework version number (from 1.x to 2.x) and directly removed the
conflicting methods, documenting all the changes I've done and writing
a small migration document.

So finally I choused to avoid the deprecation problem after all, but it
was a useful discution anyway.

Regards,
Gabriel
 

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

No members online now.

Forum statistics

Threads
474,264
Messages
2,571,065
Members
48,770
Latest member
ElysaD

Latest Threads

Top