implementing method with different return type

P

Pradeep Kumar

Hi all ......

suppose a code ..

interface one {
Object methodOne();
}

class two implements one {
public String methodOne() {
return "";
}
}


now as i implmented a interface "one" in class "two".. i changed the return
type to a subclass of Object "String".. this is perfectlly valid in term of
logic or concept... but java compiler is giving an error ... compiler says
that prototype is not same .. this is fine ...

now my question is why java compiler make such type of restriction ... i
think there is no problem in declaring return type as any subclass ...

any suggestion / answer / hint ?????????????
 
V

VisionSet

Pradeep Kumar said:
Hi all ......

suppose a code ..

interface one {
Object methodOne();
}

class two implements one {
public String methodOne() {
return "";
}
}

The signature must be the same.
Try:
interface one {
Object methodOne();
}

class two implements one {
public Object methodOne() {
return "";
}
}

And cast the result back to String after calling methodOne()
 
P

Peter Kirk

VisionSet said:
The signature must be the same.

I think the "signature" is the same (isn't it the case that "signature" is
defined as the method's name and parameters, but does not include its return
type?).

It is the return type that the OP wants to be different. And this is not
possible in Java, except as you specify below...
 
D

Dale King

Pradeep Kumar said:
Hi all ......

suppose a code ..

interface one {
Object methodOne();
}

class two implements one {
public String methodOne() {
return "";
}
}


now as i implmented a interface "one" in class "two".. i changed the return
type to a subclass of Object "String".. this is perfectlly valid in term of
logic or concept... but java compiler is giving an error ... compiler says
that prototype is not same .. this is fine ...

now my question is why java compiler make such type of restriction ... i
think there is no problem in declaring return type as any subclass ...

any suggestion / answer / hint ?????????????

This restriction will be removed in JDK 1.5.
 
V

VisionSet

Peter Kirk said:
I think the "signature" is the same (isn't it the case that "signature" is
defined as the method's name and parameters, but does not include its return
type?).

It is the return type that the OP wants to be different. And this is not
possible in Java, except as you specify below...

You are correct, I was being sloppy for clarity, if that makes any sense ;-)
Perhaps someone knows the term for the full first line of code that defines
a method?
 
P

Peter

Dale King said:
This restriction will be removed in JDK 1.5.

Does this also mean that methods could be "overloaded" like this:

void foo();
int foo();
Long foo();

?
 
C

Christophe Vanfleteren

Peter said:
Does this also mean that methods could be "overloaded" like this:

void foo();
int foo();
Long foo();

?

No, you can substitute the return type for one of it's subclasses (eg, from
Object to String). That way, you can still treat the subtype as its
supertype, which wouldn't be possible in your examples.
 
J

Joona I Palaste

No, you can substitute the return type for one of it's subclasses (eg, from
Object to String). That way, you can still treat the subtype as its
supertype, which wouldn't be possible in your examples.

IMHO overridden methods should be able to widen the types of their
parameters, and to narrow the types of their return values. This would
make the contract with the overridden method more generous than that
with the original method, so the original contract would still work.
The opposite is forbidden: overridden methods should not be able to
narrow the types of their parameters, nor widen the types of their
return values. The maxim for this is: the caller of the method should
not need to know, or care about, whether the method has been
overridden.
I also feel that methods should not be overloaded based on return types.
Because this would mean that the right methods is only chosen by how the
resulting value is used - assigned to a variable of a specific type, for
example, and so things would get extremely hairy.

Imagine a case like this, for example:

public class A {
public Object foo() { /* ... */ }
public String foo() { /* ... */ }
}

/* ... */
System.out.println("Hello, " + new A().foo());

or even a case like this:

public class A {
public Object foo() { /* ... */ }
public String foo() { /* ... */ }
}

/* ... */
new A().foo();

How should the Java compiler be able to decide the correct
implementation? IMHO, making a decision such as this based on code
*outside* the method call itself causes hopelessly complicated syntax
rules.
 
J

Joona I Palaste

Dale King said:
Hello, Peter!
No, you can only override with a subclass of the return type of
the inherited method signature. Previously, it had to be the
exact same class and in 1.5 they relax that to include
subclasses. It's caled covariant return types and is a necessity
with the introduction of generics.

Over*ride*, that is, not over*load*. The method in the subclass does the
job of the same method in the superclass. The dispatch is resolved at
run-time, unlike in overloading, where it is resolved completely
statically at compile-time.
You can *never* overload methods on return types. With Java 1.5 you can
override them on return types under some circumstances.
 
R

Roedy Green

compiler says
that prototype is not same .. this is fine ...

No it is not fine. You cannot have two methods that differ only in
return type. The problem is, how would Java decide which of them to
use?

consider:

(new Dog).bark();

Where you have two kinds of bark methods, on that returns a Tree and
one that returns a Noise. How could Java decide which to invoke? It
needs the arguments to differ to decide.
 
R

Roedy Green

The is something I think you should be able to do,

return Dalmatian in a method that overrides a method that returns Dog.

It is better documentation, and a built in assertion.
 
T

Tony Morris

I think the "signature" is the same (isn't it the case that "signature"
is
Nope.
A method signature is defined by the method's name and THE ORDER and type of
its parameters.

1.5 includes covariant return types.
This is not the same as allowing an overridden method to return any
arbitrary type, but only one which can be implicitly converted.
Without going into detail and repeating what a JSR already specifies (I
think it's JSR-014 off the top of my head), I can only suggest reading up on
it.

--
Tony Morris
(BInfTech, Cert 3 I.T.)
Software Engineer
(2003 VTR1000F)
Sun Certified Programmer for the Java 2 Platform (1.4)
Sun Certified Developer for the Java 2 Platform
 
V

VisionSet

Tony Morris said:
"signature"

Nope.
A method signature is defined by the method's name and THE ORDER and type of
its parameters.

Sheesh! The guy wasn't wrong, just brief!!
 
R

Roedy Green

return Dalmatian in a method that overrides a method that returns Dog.

It is better documentation, and a built in assertion.

Also when you use it with a specific reference, you don't need to cast
the result back to Dalmatian.
 
N

Neal Gafter

Roedy said:
No it is not fine. You cannot have two methods that differ only in
return type. The problem is, how would Java decide which of them to
use?

Given that one overrides the other, the compiler doesn't need to decide. JDK
1.5.0 allows the overriding method to return a more specific type than the
overridden method.
 
N

Neal Gafter

Joona said:
IMHO overridden methods should be able to widen the types of their
parameters, and to narrow the types of their return values. This would
make the contract with the overridden method more generous than that
with the original method, so the original contract would still work.

I agree. Unfortunately, it is too late to make that change in the Java
programming language, because it would break lots of existing code.
Specifically, it would make methods that used to be overloadings into
overriders. Such a generalization of the language probably requires disallowing
many kinds of overloading. For example, if you have a pair of instance methods

void f(String)
void f(Object)

there would be be no way to override the second without also overriding the
first. Therefore these overloading should probably be disallowed. I suspect a
language designed this way would do away with overloading altogether.
 
M

Mike Schilling

Joona I Palaste said:
Dale King said:
Hello, Peter!
You said:
"Dale King" <kingd[at]tmicha[dot]net> skrev i en meddelelse
<snip>
now my question is why java compiler make such type of restriction ... i
think there is no problem in declaring return type as any subclass ...

any suggestion / answer / hint ?????????????

This restriction will be removed in JDK 1.5.

Does this also mean that methods could be "overloaded" like this:

void foo();
int foo();
Long foo();
No, you can only override with a subclass of the return type of
the inherited method signature. Previously, it had to be the
exact same class and in 1.5 they relax that to include
subclasses. It's caled covariant return types and is a necessity
with the introduction of generics.

Over*ride*, that is, not over*load*. The method in the subclass does the
job of the same method in the superclass. The dispatch is resolved at
run-time, unlike in overloading, where it is resolved completely
statically at compile-time.
You can *never* overload methods on return types. With Java 1.5 you can
override them on return types under some circumstances.

"Override on" sounds odd to me. I think you mean to say that in Java 1.5
you can change the return type when overriding a method, subject to some
constraints.
 
R

Roedy Green

Given that one overrides the other, the compiler doesn't need to decide. JDK
1.5.0 allows the overriding method to return a more specific type than the
overridden method.

You can't have two methods in the same class that differ only in
return type.

Let's say you were allowed to write something like this:
class Salmon
{
int catch();
}

class Coho extends Salmon
{
String catch();
}


now you write code like this

Salmon s;
....
c = (s.catch()) + 4;

The compiler would have to deal with the result being either a string
or an int. In one case the + is concatentation and the other
addition.

You have created a can of worms.

1.5 restricts you to return a subclass of the base class return
method.

1.4 insists they exactly match.
 
J

Joona I Palaste

Mike Schilling said:
Joona I Palaste said:
Dale King said:
Hello, Peter!
You wrote:
"Dale King" <kingd[at]tmicha[dot]net> skrev i en meddelelse
<snip>
now my question is why java compiler make such type of
restriction ... i
think there is no problem in declaring return type as any
subclass ...

any suggestion / answer / hint ?????????????

This restriction will be removed in JDK 1.5.

Does this also mean that methods could be "overloaded" like
this:

void foo();
int foo();
Long foo();
No, you can only override with a subclass of the return type of
the inherited method signature. Previously, it had to be the
exact same class and in 1.5 they relax that to include
subclasses. It's caled covariant return types and is a necessity
with the introduction of generics.

Over*ride*, that is, not over*load*. The method in the subclass does the
job of the same method in the superclass. The dispatch is resolved at
run-time, unlike in overloading, where it is resolved completely
statically at compile-time.
You can *never* overload methods on return types. With Java 1.5 you can
override them on return types under some circumstances.
"Override on" sounds odd to me. I think you mean to say that in Java 1.5
you can change the return type when overriding a method, subject to some
constraints.

Yes, that's what I meant to say. It was almost midnight and I had had a
glass of Foster's when I wrote that so I didn't get my terminology quite
straight.

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"The large yellow ships hung in the sky in exactly the same way that bricks
don't."
- Douglas Adams
 
M

Mike Schilling

Dale King said:
Hello, Peter!


No, you can only override with a subclass of the return type of
the inherited method signature. Previously, it had to be the
exact same class and in 1.5 they relax that to include
subclasses. It's caled covariant return types and is a necessity
with the introduction of generics.

By the way, it's interesting to note that 1.5 does this with a compiler
trick. Given

class Base { Object foo() ; }
class Derived extends Base { String foo(); }

The compiler generates a second method Foo in Derived:

Object foo() { return the-String()-version-of-foo(); }

so that the JVM needn't do anything special to dispatch virtual calls. In
fact, covariance is allowed in 1.5 javac even if you compile for source and
target versions of 1.3, and the resulting class file seems to work fine in a
1.3 JVM, though it crashes 1.3 javap.
 

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
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top