Heejin
Heejin

Reputation: 4571

Better way to avoid casting?

I have interface Foo

public interface Foo {
    public void test();
}

Class FooChild implements interface Foo.

public class FooChild implements Foo {

    @Override
    public void test() {...}

    public void test2() {...}
}

I have to call function test2 in somewhere in the code.

Foo f = new FooChild();
((FooChild) f).test2();

I really hate casting an interface to a class.

So I added another interface Bar.

public interface Bar extends Foo {
    public void test2();
}

public class FooChild implements Bar {

    @Override
    public void test() {...}

    @Override
    public void test2() {...}
}

Now I call test2() with casting to an interface, not a class.

Foo f = new FooChild();
((Bar) f).test2();

I may add function test2 to the interface Foo, but there are too many classes that implement Foo.

If I add the function, I have to add codes to all the classes that implement Foo.

Although I can do that above, I actually don't have permission to edit Foo.

Will there be any fancier way to solve this problem? (hopefully without casting)

EDIT: f is passed as a method parameter.

As Jon said, I should have be more specific. Sorry for the confusion.

public void doSomething(Foo f) {
...
}

Upvotes: 1

Views: 3286

Answers (3)

JMoy
JMoy

Reputation: 491

Hard to say what you exactly want here, but you could possibly create a helper function for any Foo objects to return a FooChild..

public FooChild getImpl(Foo input){
  if (input instanceof FooChild){
    return (FooChild)input;
  }else{
    return null;
  }
}

that way you call your helper function like so (assuming not null:

getImpl(f).test2();

Note: this code does not check for nulls at all, which you would need to do in your code.

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500775

If you know that the variable value really has to be of type FooChild, just declare it that way:

FooChild f = new FooChild();
f.test2();

If there's some reason why that won't work for you, it's something you haven't told us...

EDIT: Okay, so apparently it's really a method parameter:

public void doSomething(Foo f) {
    ((FooChild) f).test2();
}

... so no, there's nothing you can do to avoid the cast. The cast indicates that there's a requirement on the value beyond what the declared variable type already guarantees - in this case, you want to say "It's got to actually be a FooChild, not just any implementation of Foo." Casts are the way of expressing that, if you can't change the parameter.

Upvotes: 6

Eugene Retunsky
Eugene Retunsky

Reputation: 13139

Bar f = new FooChild();
f.test2();

Upvotes: 5

Related Questions