2
votes

I want to call a Java method with the following API from Scala:

// Java API
public interface JavaAPI {
  JustSomeAPISpecificType clone();
}

// Scala code in class a.b.c.D
val api: JavaAPI = factory.getAPI
val result: JustSomeAPISpecificType = api.clone

However, this does not work, as the Scala compiler (2.10) thinks I want to call Object.clone:

Error: method clone in class Object cannot be accessed in Option[JavaAPI] Access to protected method clone not permitted because prefix type Option[JavaAPI] does not conform to class D in package a.b.c where the access take place

Any ideas? Thanks.

1
Can you try putting () at the end of the call to clone?wheaties
And it isn't because the interface is package protected? (No access modifier in Scala means public but package protected in Java)johanandren
JavaAPI is public. And putting () at the end of clone didn't make any difference.Michael Rueegg
Edited the question to make it more clear (added public modifier to Java interface and matched class names in error message).Michael Rueegg

1 Answers

2
votes

First of all see Object#clone() signature

protected Object clone()
                throws CloneNotSupportedException

You want to override this method.

In your example now you have two methods:

protected Object clone()
                    throws CloneNotSupportedException
public JustSomeAPISpecificType clone()

See:

JustSomeAPISpecificType.java

public enum JustSomeAPISpecificType{
INSTANCE
}

Factory.java

public class Factory {

        public static class JavaApiImpl implements JavaAPI{

                public JustSomeAPISpecificType clone(){
                        return JustSomeAPISpecificType.INSTANCE;
                }
        }

        public static JavaAPI getAPI(){
                return new JavaApiImpl();
        }
}

Now add your files to src/main/java and run sbt console from root:

scala> val api = Factory.getAPI
api: JavaAPI = Factory$JavaApiImpl@4243eb68

scala> api.getClass.getMethods.filter(m => m.getName.startsWith("clone")).mkString("\n")
res0: String = 
public JustSomeAPISpecificType Factory$JavaApiImpl.clone()
public java.lang.Object Factory$JavaApiImpl.clone() throws java.lang.CloneNotSupportedException

Update If you cast - you will see the method clone (if the factory is public).

scala> api.asInstanceOf[Factory.JavaApiImpl].clone
res4: JustSomeAPISpecificType = INSTANCE