Scala Corner Case#1: Implement Method of Java Interface with Type Parameter Omitted by It's Sub-Class

The progress of rewriting Erlang plugin for NetBeans in Scala has reached a phase, that the Editor itself works smooth and better than ErlyBird now, the next step is to integrate an Erlang project management and index the modules/functions of OTP/project to provide smart auto-completion.

Now Scala has been proved that it can be integrated into an existed large Java based framework (NetBeans IDE here) without no much problems, I'll begin to rewrite Scala plugin in Scala soon.

Although in most cases, Scala can call existed Java code or classes smoothly, there are still some corner cases. I'll record these corner cases in blogs. Here's the first one which I also posted on scala-user mailing-list, but have not yet got final answer.

Let's begin with a detailed example:

There is a Java interface A:

public interface A<T extends String> {
   void run(T t);
}

Which has a type parameter <T extends String> and abstract method run(T t)

Then a Java abstract class B extended A. But, B, as it, omitted type parameter from A. This is unsafe but valid in Java:

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

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

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

scalac will complain 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 run[T <: String](t:T) = {println(t)}

I than tried "forSome" type:

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

The code still did not work.

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

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

But I think Scala can always be saved with mixed Java/Scala code in such corner case, that's what I believed. So, I thought about it later when my brain was spare, and finally got a solution:

I wrote another Java abstract class B1 which extends B and pretended to have implemented "run(T t)", but actually called another new abstract method "runImpl(String t)"

public abstract class B1 extends B {

    public void run(String t) {
        runImpl(t);
    }

    public abstract void runImpl(String t);
}

Now I can let Scala S extends B1 and implement "runImpl(String t)" instead of extending B and implementing "run(T t)".

class S extends B1 {
    override
    def runImpl(t:String) = {println(t)}
}

Yes, scalac won't complain about "runImpl(t:String)" at all, and I got S successfully extends B by bridge class B1.

But I still hope scalac can resolve it directly, with a warning message instead of failing to compile it.

  • Posted: 2009-02-19 08:00 (Updated: 2010-01-09 10:12)
  • Author: dcaoyuan
  • Categories: Java Scala

Comments

1. Z.S. -- 2009-02-20 08:00

Hi Caoyuan, I am writing a Perl plugin 'nbPerl'. I am new to language plugin development, so I plan to imitate step by step your development of Erlang plugin, maybe even to the point of writing it in Scala. My question is, is CSL included in NetBeans 6.5? If not, how do I install the module? Please also provide any other pointers/tips that you deem helpful.

2. Caoyuan -- 2009-02-21 08:00

Z.S.

CSL is not moved to main trunk yet, you have to clone the branch:  http://hg.netbeans.org/jet-parsing-api/ and work on it.

3. Z.S. -- 2009-02-21 08:00

By working on it, do you mean, build the module? I tried to run ant in the csl.api directory, but it has failed to build with error. nbbuild/default.xml:50 taskdef class org.netbeans.nbbuil.JHIndexer cannot be found.

4. Z.S. -- 2009-02-21 08:00

When I tried to build Netbeans by going into nbbuild folder and executing ant, I got errors of the form Element <a> doesn't support nested element of type <b>.

5. Caoyuan -- 2009-02-21 08:00

Z.S:

 http://wiki.netbeans.org/WorkingWithNetBeansSources

I used to: ant clean; ant build to build whole IDE every week or so.

6. Caoyuan -- 2009-02-22 08:00

Z.S:

per <a href=" http://nbperl.blogspot.com/2009/02/using-csl-common-scripting-language-in.html">your blog entry</a>

My comment in BLOD means nothing, it was actually caused by you with a "&lt;b&gt;" at the end of your last comment input. I end it here with a "&lt;/b&gt;"</b>

For your experience, I have no much idea, since I cannot tell you why your ant version shown 1.6.5, I even don't know your os environment, you should fix it first as 1.7.1 is a requirement.

BTW, the building process is about 1 hour, this also happens on me, that's life. And I've told you that I clean and build whole things every week.

Writing language supporting is a time-consumed work, it's boring and tied, whatever under Eclipse, under NetBeans, under IDEA.

Cheers, -Caoyuan

7. donaldjeo -- 2010-05-15 11:47

An interface declaration introduces  70-299 a new reference type whose members are classes, interfaces, constants and abstract methods. This type has no implementation,  70-431 dumps but otherwise unrelated classes can implement it by providing implementations for its abstract  iseb methods. A nested interface is any interface whose declaration occurs within the body of another class or interface. A top-level  exam 70-432 dumps interface is an interface that is not a nested interface. We distinguish between two kinds of interfaces  oracle dumps - normal interfaces and annotation types. This chapter discusses the common semantics of all interfaces-normal interfaces and annotation types (§9.6), top-level (§7.6)  70-448 dumps and nested (§8.5, §9.5). Details that are specific to particular kinds of interfaces are discussed in the sections dedicated to these constructs.  mcts 70-536 dumps Programs can use interfaces to make it unnecessary for related classes to share a common abstract superclass or to add methods to Object. An interface may be declared to be a  redhat certification direct extension of one or more other interfaces, meaning that it implicitly specifies 70-553 all the member types, abstract methods and constants of the interfaces it extends, except for any member types and constants that it may hide. A class may be declared to directly implement one or more interfaces, meaning that any instance of the class implements all the abstract methods specified by the interface or interfaces. A class necessarily implements all the interfaces that its direct superclasses and direct  70-554 superinterfaces do. This (multiple) interface inheritance allows objects to support (multiple) common behaviors without sharing any implementation. A variable whose declared type is an interface type may have as its value a reference to any instance of a class which implements the specified interface. It is not sufficient that the class happen  70-562 dumps to implement all the abstract methods of the interface; the class or one of its superclasses must actually be declared to implement the interface, or else the class is not considered to implement the interface.