Как добавить атрибуты родительского класса в подкласс

#java #oop

Вопрос:

У меня есть родительский класс с именем Set , представляющий набор теннисных матчей.

 public class Set {
  private String set1;
  private String set2;
  private String set3;
  //private Object[] match;

  public Set() {
    setSet1(set1);
    setSet2(set2);
    setSet3(set3);
  }

  public void setSet1(String set1) {
    this.set1 = set1;
  }

  public String getSet1() {
    return set1;
  }

  public void setSet2(String set2) {
    this.set2 = set2;
  }

  public String getSet2() {
    return set2;
  }

  public void setSet3(String set3) {
    this.set3 = set3;
  }

  public String getSet3() {
    return set3;
  }


  public String toString(){
    return String.format("set1: %s, set2: %s, set3: %s", set1, set2, set3);
  }


}
 

и подкласс Set с именем SingleSet , в котором я пытаюсь добавить наборы в массив с именем «игра».

 public class SingleSet extends Set{
  private Object homePlayer;
  private Object awayPlayer;

  private String[] game;

  public SingleSet(Object homePlayer, Object awayPlayer){
    super();

    game = new String[3];

    game[0] = super.getSet1();
    game[1] = super.getSet2();
    game[2] = super.getSet3();

    setHomePlayer(homePlayer);
    setAwayPlayer(awayPlayer);
  }

  public void setHomePlayer(Object homePlayer) {
    this.homePlayer = homePlayer;
  }

  public Object getHomePlayer() {
    return homePlayer;
  }

  public void setAwayPlayer(Object awayPlayer) {
    this.awayPlayer = awayPlayer;
  }

  public Object getAwayPlayer() {
    return awayPlayer;
  }

  public void setGame(String[] game) {
    this.game = game;
  }

  public String[] getGame() {
    return game;
  }

  public String toString(){
    return String.format("Player: %s Vs. Player: %s, Single set game: %s, %s, %s", homePlayer, awayPlayer, game[0], game[1], game[2]);
  }
}
 

Здесь я пытаюсь добавить Set s из класса моих родителей в свой подкласс (это для FXML, поэтому код находится в моем контроллере).:

  public void submit() {
    SingleSet game1 = new SingleSet(homePlayer1Dropdown.getValue(), awayPlayer1Dropdown.getValue());
    game1.setSet1(set1Box1.getText());
    game1.setSet2(set1Box2.getText());
    game1.setSet3(set1Box3.getText());

    System.out.println(game1);
 }
 

Когда я печатаю результат, значения моего массива равны нулю. Я попытался распечатать их по отдельности, и это сработало нормально, так что я знаю set1Box.getText() , что все работает нормально.

Комментарии:

1. setSet1 и так далее, не устанавливайте значения в своем game массиве. Они устанавливают set1 и т. Д.

2. Это плохая практика, когда конструктор вызывает классы, задающие значения (как показано в первом классе), которые передаются в конструктор. Также я думаю, что вашему пониманию тенниса не хватает того, что Теннисный матч состоит из нескольких сетов, и каждый Сет состоит из нескольких игр.

3. возможно, вам придется @Переопределить метод toString. и проверьте свой сеттер и свой массив . сеттеры предназначены для set1,set2,set3. вы хотите распечатать игру[0..2]

4. Конструкторы используются для задания значений переменных экземпляра. Можно использовать собственные сеттеры, поэтому у вас может быть вся логика (например, отклонять null значения), но вы должны указать некоторые параметры своего конструктора, например public Set( String set1, String set2, String set3) . Тогда вам также следует изменить super() вызов.

5. также (не всегда) хорошо сохранять одни и те же данные несколько раз — сложнее синхронизировать их все. game Поле не обязательно — если требуется массив, просто измените getGame метод создания и заполнения массива. ( public String[] getGame() { return new String[] { getSet1(), getSet2(), getSet3() }; } )

Ответ №1:

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

SingleSet game1 = new SingleSet(homePlayer1Dropdown.getValue(), awayPlayer1Dropdown.getValue()); это создание нового SingleSet , которое расширяется Set .

SingleSet конструктор super() вызывает конструктор набора.

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

Десять одиночных наборов продолжают создавать ваш объект с заданным параметром, который ничего не делает для установки значения для set1, set2, set3.

  game1.setSet1(set1Box1.getText());
 game1.setSet2(set1Box2.getText());
 game1.setSet3(set1Box3.getText());
 

Они фактически устанавливают значение set1, set2, set3 (поскольку вы говорите, что set1Box1.getText() и другие работают). Так почему же вы все еще видите нуль при печати?

 public String toString(){
  return String.format("Player: %s Vs. Player: %s, Single set game: %s, %s, %s", homePlayer, awayPlayer, game[0], game[1], game[2]);
}
 

Вот почему: вы печатаете игру[0] и так далее, которые на самом деле являются нулевыми, потому что, когда вы устанавливаете свой игровой массив, эти значения становятся нулевыми!

 public SingleSet(Object homePlayer, Object awayPlayer){
  super(); //setting null values to set1, set2, set3

  game = new String[3];

  game[0] = super.getSet1(); //this returns null!
  game[1] = super.getSet2(); //this returns null!
  game[2] = super.getSet3(); //this returns null!

  setHomePlayer(homePlayer);
  setAwayPlayer(awayPlayer);
}
 

Распечатайте некоторые значения, когда вы создадите свой объект, и увидите 🙂

Чтобы решить эту проблему, один из способов-использовать параметризованный конструктор public Set(String set1, String set2, String set3) , использовать параметризованный дочерний конструктор public SingleSet(String set1, String set2, String set3, Object homePlayer, Object awayPlayer) и параметризованный вызов super, super(set1, set2, set3)

Затем вы должны установить значения при создании game1 SingleSet game1 = new SingleSet(set1Box1.getText(), set1Box1.getText(), set1Box1.getText()homePlayer1Dropdown.getValue(), awayPlayer1Dropdown.getValue());

Ответ №2:

  1. Вы ничего не устанавливаете в конструкторе набора по умолчанию
  2. Действительно следует найти лучшее название для вашего класса, так как «Набор» путается с набором коллекций.
  3. Используйте неизменяемый для обоих ваших классов, чтобы уберечь себя от неприятностей — удалите все установщики и инициализируйте в конструкторе.
  4. Я не очень хорошо разбираюсь в правилах подсчета очков в теннисе, но, насколько мне известно, в «наборе» есть несколько «игр», а «матч» состоит из нескольких наборов. Какова логика этого отношения «Набор Что делать, если вы измените свою иерархию таким образом (в псевдокоде для краткости пропустите большинство тел методов):
 class Player{
  private String name;
  public Player(String name);
}

class Match{
  private Player homePlayer;
  private Player awayPlayer;
  private List<Set> sets;
  public Match(Player homePlayer, Public awayPlayer);
  public List<Set> getSets(){
    if(sets == null){
      sets = new ArrayList<>();
    }
    return sets;
  }
}

class Set{
  public Set(Game... games);
}

class Game{
  // game score details
  public Game(int scoreHomePlayer, int scoreAwayPlayer);
}

 

Чтобы в вашем контроллере вы могли использовать его следующим образом:

 Match match = new Match(new Player("Williams"), new Player("Johnson"))
match.getSets().add(new Set(
   new Game(6, 1),
   new Game(4, 6),
   new Game(7, 0)
   // etc.
))
 
  1. Вы могли бы дополнительно реорганизовать иерархию #4 и избавить всех от этих вызовов конструктора «new ()», используя шаблон конструктора, что-то в этом роде:
 Match match = new MatchBuilder("Williams","Johnson").addSet()
  .addGame(6,1).addGame(4,6).addGame(7,0)
  .build()
 

Ответ №3:

вы должны переопределить метод set .Вместо в наборе после создания экземпляра конструктора

  public SingleSet(Object homePlayer, Object awayPlayer) {
        super();

        game = new String[3];

//        game[0] = super.getSet1();
//        game[1] = super.getSet2();
//        game[2] = super.getSet3();

        setHomePlayer(homePlayer);
        setAwayPlayer(awayPlayer);
    }
    @Override
    public void setSet1(String set1) {
        this.game[0]=set1;
        super.setSet1(set1);
    }

    @Override
    public void setSet2(String set2) {
        this.game[1]=set2;
        super.setSet2(set2);
    }

    @Override
    public void setSet3(String set3) {
        this.game[2]=set3;
        super.setSet3(set3);
    }