andersra
andersra

Reputation: 1135

How to implement an interface on a protected java class

I was looking to implement an interface on a package-private java class, but I am having some difficulty achieving this. Below is an example.

class Foo
{
    String something(String str)
    {
        return ""str+"!";
    }
}




public interface Bar
{
    String something(String str);
}

What is the best approach here? My end goal is to implement the Bar interface on the Foo class. I am hoping to be able to cast Foo as Bar: (Bar)Foo

The Bar interface and the Foo class are in separate packages. Is there a way to do this?

Please advise.

Upvotes: 1

Views: 1627

Answers (5)

Ryan Amos
Ryan Amos

Reputation: 5452

You can try using bytecode injection with BCEL or ASM and setting the interface at runtime. It's tricky, though.

There might also be a way to change interaces with reflection, but I doubt it.

Private is there for a reason.

Upvotes: 0

OscarRyz
OscarRyz

Reputation: 199215

You can't. The point of having the package level access it to precisely avoid seeing that class outside. What you can do however ( granted Foo is not final ) something like this:

C:\>type *.java
//Foo.java
package foo;
class Foo {
  String something( String s ) {
    return s + "!";
  }
}  
//Bar.java
package bar;
public interface Bar {
  public String something( String s );
}    
//Baz.java
package foo;    
import bar.Bar;    
public class Baz extends Foo implements Bar {
  // make sure you're overriding
  @Override
  public String something ( String s ) {
    return super.something( s );
  }
}     
//Use it: Main.java
package bar;
import foo.Baz;   
class Main {
  public static void main( String ... args ) {
    Bar bar = new Baz();
    System.out.println( bar.something("like this?"));
  }
}

C:\>java bar.Main
like this?!

Da da!

The trick is to define the child in the same package as the parent so you can create a public version of it.

I hope this helps.

Upvotes: 2

ide
ide

Reputation: 20788

You'll need to use inheritance or composition if you don't have access to the source code of Foo.

// By logically including your code in the package containing Foo,
// you can now access it. If Foo belongs to the default package, sorry.
// This also doesn't work if the package is sealed.
package where.foo.resides;

public interface Bar {
    String something(String s);
}

// Inheritance
public class FooBar extends Foo implements Bar {
    public String something(String s) {
        return super.something(s);
    }
}

// Composition
public class ComposedFooBar implements Bar {
    private final Foo delegate;
    public ComposedFooBar(Foo delegate) {
        this.delegate = delegate;
    }
    public String something(String s) {
        return delegate.something(s);
    }
}

Upvotes: 1

Zach L
Zach L

Reputation: 16262

Foo needs to implement Bar

protected class Foo implements Bar

Also, I think Foo.something needs to be public in order to implement Bar.something

Side Note: While it was probably just as an example,

return ""str+"!";

should be:

return str + "!";

If Foo is package private, and you don't have access to the source, just the classfiles and/or the jar containing Foo.class, there's not much to do -- something that is package private is invisible to classes in the default package (where there is no package specified) and other packages.

Upvotes: 1

Aravind Yarram
Aravind Yarram

Reputation: 80176

When you doesn't have control on a class but you want to make it look like an API that you have, then you Adapt it to fit your needs. Hint: Adapter Pattern

Upvotes: 2

Related Questions