#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:
- Вы ничего не устанавливаете в конструкторе набора по умолчанию
- Действительно следует найти лучшее название для вашего класса, так как «Набор» путается с набором коллекций.
- Используйте неизменяемый для обоих ваших классов, чтобы уберечь себя от неприятностей — удалите все установщики и инициализируйте в конструкторе.
- Я не очень хорошо разбираюсь в правилах подсчета очков в теннисе, но, насколько мне известно, в «наборе» есть несколько «игр», а «матч» состоит из нескольких наборов. Какова логика этого отношения «Набор Что делать, если вы измените свою иерархию таким образом (в псевдокоде для краткости пропустите большинство тел методов):
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.
))
- Вы могли бы дополнительно реорганизовать иерархию #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);
}