Используйте более конкретный тип данных в перегруженном методе в Java - PullRequest
2 голосов
/ 02 декабря 2009

У меня есть некоторый массив с различными объектами одного и того же типа интерфейса, например:

Interface interface {}

class A implements interface {}

class B implements interface {}

У меня также есть перегруженный метод, который реализует все эти унаследованные объекты интерфейса:

public void doSomething(A obj) {}

public void doSomething(B obj) {}

Компилятор также заставляет меня написать перегруженный метод с интерфейсом:

public void doSomething(interface obj) {}

Затем я просматриваю значения списка и вызываю метод:

for (interface obj: myList) {
   doSomething(obj);
}

Теперь, поскольку тип obj - «интерфейс», вызывается doSomething (интерфейс obj) вместо, скажем, doSomething (B obj) в случае, если объект obj действительно имеет тип B.

Могу ли я заставить java делать иначе, поэтому он вызывает doSomething (A obj), когда obj имеет тип A, и doSomething (B obj), когда obj имеет тип B?

Ответы [ 5 ]

3 голосов
/ 02 декабря 2009

Java использует раннее связывание, что означает, что тип obj определяется во время компиляции, а не во время выполнения. Поскольку ваш код говорит, что obj имеет тип interface, компилятор всегда будет вызывать метод, который получает интерфейс в качестве параметра.

У вас есть два варианта вызова правильного метода:

  1. (Очень уродливо) Проверьте тип obj с помощью instanceof и приведите во время вызова объекта.

    for (interface obj: myList) {
       if(obj instanceof A)
          doSomething((A) obj);
       else if(obj instanceof B)
          doSomething((B) obj);
       else
          doSomething(obj); // Calls the method receiving Interface
    }
    
  2. Реализация метода посетителя в интерфейсе, чтобы и A, и B вызывали метод doSomething (this) при посещении.

    interface Interface {
        void visit(OtherClass methodHolder);
    }
    
    class A implements Interface {
        public void visit(OtherClass methodHolder) {
            methodHolder.doSomething(this);
        }
    }
    
    class B implements Interface {
        public void visit(OtherClass methodHolder) {
            methodHolder.doSomething(this);
        }
    }
    
2 голосов
/ 02 декабря 2009

Есть хитрость. Отказ от ответственности: это некрасиво.

Если ваш класс с методами doSomething называется class Performer, например:

class Performer {
  void doSomething(A x);
  void doSomething(B x);
  void doSomething(Inf x);
}

Вы можете добавить в свой интерфейс Ifc:

interface Ifc {
  void acceptPerformer(Performer p);
}

В обоих классах A и B реализовать это так:

void acceptPerformer(Performer p) {
  p.doSomething(this);
}

И реализуйте свой метод doSomething (Ifc x) следующим образом:

void doSomething(Ifc x) {
  x.acceptPerformer(this);
}

Звучит странно, но работает. При вызове метода doSomething, который принимает интерфейс, он вызовет acceptPerformer для конкретного класса . Когда этот класс повторно вызывает doSomething, он будет знать, какой это тип и будет вызывать правильный doSomething!

0 голосов
/ 02 декабря 2009

Это метод

public void doSomething(interface obj)

определен как часть интерфейса? Это единственное, что имеет смысл, если компилятор заставляет вас писать метод.

Тогда возникает вопрос, почему вы пытаетесь изменить сигнатуру метода интерфейса в ваших реализациях. Интерфейс должен быть контрактом на то, как выглядит объект.

0 голосов
/ 02 декабря 2009

Полиморфный подход заключается в определении doSomthing() в вашем interface и реализации его в A и B, а затем вызове его в вашем цикле. В зависимости от конкретного объекта будет выполняться другой код.

0 голосов
/ 02 декабря 2009

Вы можете использовать оператор Java instanceof, чтобы проверить, какой класс реализует ваш интерфейс:

if(obj instanceof A) {
    // do something
} else {
    // do something else
}

Но лучшим подходом является использование метода, который будет просто брать любой объект, который является экземпляром интерфейса, который вы создали, как упомянуто Atmocreations.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...