Переопределить данные члена в подклассе, использовать в реализации суперкласса? - PullRequest
4 голосов
/ 19 сентября 2009

Можно ли в Java переопределить данные-члены в подклассе, и эта переопределенная версия будет данными, используемыми в реализации суперкласса?

Другими словами, вот что я пытаюсь добиться, а этого не происходит:

abstract public class BasicStuff {
        protected String[] stuff = { "Pizza", "Shoes" };

        public void readStuff() {
                for(String p : stuff) { 
                        system.out.println(p); 
                }
        }
}

..

public class HardStuff extends BasicStuff {
        protected String[] stuff = { "Harmonica", "Saxophone", "Particle Accelerator" };
}

Этот вызов:

HardStuff sf = new HardStuff();
sf.readStuff();

... печатает Pizza и Shoes. Вместо этого я хочу напечатать последний.

Я понимаю, что это довольно плохая иерархическая ОО-практика; Я нуждался в этом для очень конкретного случая, так как я что-то делаю с настройкой и отражением XML.

Есть ли модификатор, который может это сделать?

И да, я признаю, что есть обертки, которые можно использовать, чтобы обойти эту проблему в моем подклассе, то есть, указав, что содержимое stuff[] теперь хранится, например, в массиве с другим именем. Я просто стараюсь быть простым и мне любопытно в принципе.

Заранее большое спасибо!

Ответы [ 3 ]

13 голосов
/ 19 сентября 2009

Я считаю, что вы должны вставить метод доступа, то есть использовать:

    for(String p : getStuff()) { 

в суперклассе и добавьте:

    protected String[] getStuff() { return stuff; }

везде, где у вас есть protected String[] stuff переопределение.

Переопределение действительно применяется к методам, а не к данным (по крайней мере, так обстоит дело в модели Java; некоторые другие языки работают иначе), поэтому для получения эффекта переопределения необходимо вставить метод ( как правило, простой грязный аксессуар, как здесь). Это на самом деле ничего не усложняет, это просто очень простой способ дать указание компилятору Java использовать, по сути, «дополнительный уровень косвенности», который требуется вашему желаемому поведению.

4 голосов
/ 19 сентября 2009

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

Попробуйте указать значение вещи в блоке инициализации (или в конструкторе):

abstract public class BasicStuff {
  protected String[] stuff;

  {
    stuff = new String[] { "Pizza", "Shoes" };
  }

  public void readStuff() {
    for(String p : stuff) { 
      System.out.println(p); 
    }
  }
}

..

public class HardStuff extends BasicStuff {
  {
    stuff = new String[] { "Harmonica", "Saxophone", "Particle Accelerator" };
  }
}
0 голосов
/ 26 июля 2014

Если вы хотите напечатать массив String Stuff, определенный в производном классе, вам нужно переопределить метод readStuff в классе HardStuff, переопределив метод в классе HardStuff. Поскольку метод readStuff был определен в абстрактном классе BasicStuff, следовательно, он будет печатать только члены класса BasicStuff. Следовательно, добавьте тот же метод в отобранный класс также Ниже вы можете найти полный код ..

class BasicStuff {
    protected String[] stuff = { "Pizza", "Shoes" };

    public void readStuff() {
            for(String p : stuff) { 
                    System.out.println(p); 
            }
    }
}


public class HardStuff extends BasicStuff {
    protected String[] stuff = 
              { "Harmonica", 
                "Saxophone", 
                "Particle Accelerator" 
              };

    public void readStuff() {
            for(String p : stuff) { 
                    System.out.println(p); 
            }
    }
    public static void main(String []arg)
    {
     HardStuff sf = new HardStuff();
        sf.readStuff();
    }
}
...