Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot Implement Method of Java Interface with Type Parameter Omitted by It's Sub-Class #1737

Closed
scabug opened this issue Feb 20, 2009 · 9 comments
Assignees

Comments

@scabug
Copy link

scabug commented Feb 20, 2009

Minim case:

There is a Java interface A:

public interface A {
void run(T t);
}

Which has a type parameter and abstract method run(T t)

And a Java abstract class B with is sub-class of A. But, B, as it,
omitted type parameter of A. This is unsafe but valid in Java:

public abstract class B implements A {
public String me() {
return "I'm B";
}
}

Assume above class A and B have been compiled under javac, and packed
as jar library, and I can not patch it anymore. Now I need to write a
class S in Scala which extends B:

class S extends B {
override
def runT <: String = {println(t)}
}

scalac complained as:
/Users/dcaoyuan/NetBeansProjects/ScalaTestCase/src/S.scala:1: error:
class S needs to be abstract, since method run in trait A of type
(T)Unit is not defined
class S extends B {
/Users/dcaoyuan/NetBeansProjects/ScalaTestCase/src/S.scala:3: error:
method run overrides nothing
def runT <: String = {println(t)}

I than tried "forSome" type:

class S extends B {
override
def run(t:T forSome {type T <: String}) = {println(t)}
}

Again, I got:
/Users/dcaoyuan/NetBeansProjects/ScalaTestCase/src/S.scala:1: error:
class S needs to be abstract, since method run in trait A of type
(T)Unit is not defined
class S extends B {
/Users/dcaoyuan/NetBeansProjects/ScalaTestCase/src/S.scala:3: error:
method run overrides nothing
def run(t:T forSome {type T <: String}) = {println(t)}

It seems that, since B omitted A's type parameter T, I have no way to
get what is T, and can not successfully override/implement "run(T t)"
method.

I tried other forms of "forSome" usages, and always failed.

@scabug
Copy link
Author

scabug commented Feb 20, 2009

Imported From: https://issues.scala-lang.org/browse/SI-1737?orig=1
Reporter: @dcaoyuan

@scabug
Copy link
Author

scabug commented Feb 24, 2009

@lrytz said:
Is it possible to implement class S in Java? What would you use as parameter type for method run?

@scabug
Copy link
Author

scabug commented Feb 24, 2009

@dcaoyuan said:
Yes, it can be implemented in Java, use "String" is enough:

public class JS extends B {
public void run(String t) {
System.out.println(t);
}
}

@scabug
Copy link
Author

scabug commented Feb 24, 2009

@odersky said:
Scala does not understand raw types. This is some of the ``baggage_ that we dropped from Java. When Scala sees a raw type it treats it as an existential. Unfortunately, that means that in the case above class B extends A with some unknown type parameter T. Since T is unknown, we can't implement a run method with this type. So we are stuck.

The only thing one can do in these situations is implement a subclass in Java that implements the method. I'm afraid there's nothing else we can do without introducing raw types into Scala. And the latter we want to avoid.

@scabug
Copy link
Author

scabug commented Feb 24, 2009

@paulp said:
If we can reliably recognize these situations, I think it would be hugely helpful for the error message to say something to the effect that the class must be implemented in java. In this example, when scala loads abstract class B, it ought to be able to determine that it's impossible to implement it scala, right? So once a class declares that it extends B it would generate that error.

If that sounds plausible to you I'd like to reopen this ticket as an enhancement.

@scabug
Copy link
Author

scabug commented Jun 24, 2009

michid4 said:
There seems to be a workaround for the simpler case:

public interface A<T extends String> {
    T get();
}

public abstract class B implements A {}

class C extends B {
    this: A[_] =>
    def get = "foo"
}

See http://michid.wordpress.com/2009/06/24/puzzle-implement-this-solution/

If we could actually refer to the existential type used in the self type, this could probably also be used to work around the original issue.

@scabug
Copy link
Author

scabug commented Sep 8, 2009

@adriaanm said:
fails in r18657 with cyclic reference error:

error: illegal cyclic reference involving type _$$1
           this: A[_] =>
                       ^

@scabug
Copy link
Author

scabug commented Sep 15, 2009

@cunei said:
Reassigning to Adriaan in the meantime, we can discuss it further in two weeks.

@scabug
Copy link
Author

scabug commented Jan 18, 2010

@paulp said:
(In r20559) Test case closes #1737. Review by community.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants