Лучший способ избежать кастинга? - PullRequest
1 голос
/ 03 апреля 2012

У меня есть интерфейс Foo

public interface Foo {
    public void test();
}

Класс FooChild реализует интерфейс Foo.

public class FooChild implements Foo {

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

    public void test2() {...}
}

Мне нужно вызвать функцию test2 где-нибудь в коде.

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

Я действительно ненавижу приводить интерфейс к классу.

Итак, я добавил еще один интерфейс Bar.

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

public class FooChild implements Bar {

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

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

Теперь я вызываю test2 () с приведением к интерфейсу, а не к классу.

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

Я могу добавить функцию test2 в интерфейс Foo, но есть слишком много классов, которые реализуют Foo.

Если я добавлю функцию, я должен добавить коды ко всем классам, которые реализуют Foo.

Хотя я могу сделать это выше, у меня фактически нет разрешения редактировать Foo.

Будет ли какой-нибудь причудливый способ решить эту проблему? (надеюсь, без кастинга)

EDIT: f передается как параметр метода.

Как сказал Джон, я должен был быть более конкретным. Извините за путаницу.

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

Ответы [ 3 ]

6 голосов
/ 03 апреля 2012

Если вы знаете, что значение переменной действительно имеет типа FooChild, просто объявите это так:

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

Если есть какая-то причина, почему это не сработает для вас, это то, что вы нам не сказали ...

РЕДАКТИРОВАТЬ: Хорошо, так что, очевидно, это действительно параметр метода:

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

... так нет, вы ничего не можете сделать, чтобы избежать актерского состава. Приведение указывает, что существует требование к значению сверх того, что уже гарантировано объявленным типом переменной - в этом случае вы хотите сказать: «На самом деле это должен быть FooChild, а не просто любая реализация Foo». Кастинг способ выразить это, если вы не можете изменить параметр.

5 голосов
/ 03 апреля 2012
Bar f = new FooChild();
f.test2();
1 голос
/ 03 апреля 2012

Сложно сказать, чего именно вы хотите, но вы можете создать вспомогательную функцию для любых объектов Foo, которая будет возвращать FooChild.

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

таким образом вы вызываете свою вспомогательную функцию следующим образом (при условии, что это не NULL:

getImpl(f).test2();

Примечание: этот код вообще не проверяет наличие нулей, что вам нужно сделать в вашем коде.

...