Как я могу изменить сигнатуру функции-члена для производного класса в Java - PullRequest
3 голосов
/ 12 ноября 2008

Во-первых, я расширяю существующую структуру класса и не могу изменить оригинал с этим предупреждением:

Я хотел бы сделать это:

class a
{
   int val;

   ... // usual constructor, etc...

   public int displayAlteredValue(int inp)
   {
     return (val*inp);
   }
}

class b extends a
{
   ... // usual constructor, etc...

   public in displayAlteredValue(int inp1, int inp2)
   {
     return (val*inp1*inp2);
   }
}

Как я уже говорил, я не могу изменить class a и хочу сохранить имя функции displayAlteredValue вместо создания новой функции. Если это можно сделать, мне нужно всего лишь изменить несколько экземпляров a на экземпляры b. Я не хочу тратить много времени на замену многих вызовов функций на displayAlteredValue. (И да, я понимаю, что существуют такие вещи, как поиск и замена, однако по другим причинам это было бы проблематично).

Есть идеи?

Ответы [ 7 ]

3 голосов
/ 12 ноября 2008

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

public class DerivedOverload {

    /**
     * @param args
     */
    public static void main(String[] args) {
        A classA = new A(); 

        B classB = new B();

        System.out.println("DerivedOverload.main() classA.displayAlteredValue(2) : " + classA.displayAlteredValue(2));

        System.out.println("DerivedOverload.main() classA.displayAlteredValue(2) : " + classB.displayAlteredValue(2,2));
    }



}


class A
{
   int val = 2;

   A(){

   }

   public int displayAlteredValue(int inp)
   {
     return (val*inp);
   }
}

class B extends A
{
   B(){

   }

   public int displayAlteredValue(int inp1, int inp2)
   {
     return (val*inp1*inp2);
   }
}

Системный выход. DerivedOverload.main () classA.displayAlteredValue (2): 4 DerivedOverload.main () classA.displayAlteredValue (2): 8

2 голосов
/ 12 ноября 2008

Мне не понятно, в чем проблема. Вы абсолютно можете создать подкласс b, у которого есть метод с тем же именем, но с другой подписью.

Одна из возможных проблем, с которой вы можете столкнуться, заключается в том, что компилятору необходимо знать, что тип объекта - b, а не a, чтобы вызвать метод, существующий только в b.

Таким образом, такой код не будет работать:

// this works because b is a subclass of a
a anObject = new b();

// this will not compile because the declared type of anObject is a
int x = anObject.getValue( 1, 2 );

Вам придется либо изменить объявление переменной на тип b, либо привести его к b, когда вы захотите вызвать метод с двумя аргументами.

1 голос
/ 13 ноября 2008

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

http://www.artima.com/lejava/articles/designprinciples4.html

1 голос
/ 12 ноября 2008

То, что у тебя есть, прекрасно для меня выглядит.

Экземпляры класса b будут иметь доступ к обеим версиям метода. Вызовы с 1 аргументом будут автоматически перенаправлены в класс a. Звонки для 2-арговой версии перейдут в класс b.

Экземпляры класса a будут иметь доступ только к версии с 1 аргументом, но я не думаю, что есть способ обойти это.

1 голос
/ 12 ноября 2008

Код, который вы написали, компилируется как есть. Вы просто перегрузили метод. Чего не удалось опубликовать в коде, который вы хотите выполнить? Вы пытаетесь помешать людям вызывать b.displayAlteredValue с одним аргументом? Если это так, вы не можете сделать это (во время компиляции), поскольку это нарушит принцип замещаемости Лискова.

Вы могли бы бросить исключение, но это было бы ужасно приятно.

В качестве альтернативы, вы можете использовать композицию вместо наследования - но на самом деле нам нужно знать больше о ситуации, чтобы узнать, подходит ли она.

1 голос
/ 12 ноября 2008

что если вы добавите это в свой производный класс

public int displayAlteredValue(int inp)
{
  return super.displayAlteredValue(inp);
}
0 голосов
/ 12 ноября 2008

Вы можете написать код в классе B следующим образом:

public int displayAlteredValue(int inp) 
{
    return -1;
}

и укажите на функции, что -1 - возврат ошибки. Для int это на самом деле не работает, но если вы вернули класс, вы можете вернуть null, если они вызывают версию метода с одним параметром.

...