Я новичок в Java и изо всех сил пытаюсь понять, почему я продолжаю получать сообщение об ошибке в командной строке. У меня есть суперкласс Guest с переменными guestID, fName, lName и dateJoin. У меня также есть подкласс VIPGuest с дополнительными переменными VIPstartDate и VIPexpiryDate.
У меня есть гости ArrayList, в которых хранятся все гостевые объекты, которые есть в моих записях. Я хочу выполнить итерацию по ArrayList и записать каждого гостя в текстовый файл с каждым гостем в новой строке в форме guestID, fName, lName, dateJoin, разделенных запятыми (или guestID, fName, lName, dateJoin, VIPstartDate, VIPexpiryDate, если Гость — это VIP-гость).
Мой код ниже. Он отлично работает, когда я использую аналогичный код, чтобы сделать то же самое для ArrayList объектов класса без подклассов, но когда я пытаюсь обойти тот факт, что у некоторых гостей есть дополнительные переменные, возникает ошибка:
HotelImpl.java:440: error: cannot find symbol
+ "," + g.getVIPstartDate() + "," + g.getVIPexpiryDate());
^
symbol: method getVIPstartDate()
location: variable g of type Guest
HotelImpl.java:440: error: cannot find symbol
+ "," + g.getVIPstartDate() + "," + g.getVIPexpiryDate());
^
symbol: method getVIPexpiryDate()
location: variable g of type Guest
2 errors
Я вижу, что у него проблемы с дополнительными переменными для объектов VIPGuest, но я думал, что исправил это с помощью if/else:
public boolean saveGuestsData(String guestsTxtFileName){
BufferedWriter writer;
try{
writer = new BufferedWriter(new FileWriter(guestsTxtFileName));
} catch (IOException e){
System.out.print("Invalid file.");
return false;
}
try{
for (Guest g : guests){
if (!(g instanceof VIPGuest)){
writer.write(
g.getGuestID() + "," + g.getFName() + "," + getLName()
+ "," + g.getDateJoin());
}
else {
writer.write(
g.getGuestID() + "," + g.getFName() + "," +
getLName() + "," + g.getDateJoin() + "," +
g.getVIPstartDate() + "," + g.getVIPexpiryDate());
}
writer.newLine();
}
writer.close();
return true;
} catch (FileNotFoundException ex) {
System.out.print("File not found.");
return false;
} catch (IOException e){
System.out.print("Invalid file.");
return false;
}
}
Это исправило это! Спасибо :)
@Habilee, я рекомендую вам использовать IDE, она объяснит вам этот тип ошибки.




В этом ответе я предполагаю, что VIPGuest расширяет Guest.
Прежде чем вы сможете использовать любой из методов VIPGuest на обычном Guest, вам нужно преобразовать гостя в VIP-гостя.
for (Guest g : guests){
if (!(g instanceof VIPGuest)){
// omitted for brevity
} else {
VIPGuest vip = (VIPGuest)g;
writer.write(vip.getGuestID() + "," + vip.getFName() + "," + vip.getLName() + "," +
vip.getDateJoin() + "," + vip.getVIPstartDate() + "," + vip.getVIPexpiryDate());
}
writer.newLine();
}
Хотя вы знаете, используя чек instanceof, что g на самом деле является VIP-гостем, ссылка на него относится только к гостю.
Обратите внимание, что если бы g на самом деле не было экземпляром VIPGuest, попытка приведения (VIPGuest)g, скорее всего, вызвала бы исключение ClassCastException.
Верно. Я собирался опубликовать аналогичный ответ;)
Ваша переменная g имеет тип Guest, и хотя экземпляр является VIPGuest, метод getVIPstartDate недоступен.
Что вы должны сделать, это:
else
{
VIPGuest vg;
vg = (VIPGuest)g;
writer.write(
vg.getGuestID() + "," + vg.getFName() + "," +
getLName() + "," + vg.getDateJoin() + "," +
vg.getVIPstartDate() + "," + vg.getVIPexpiryDate());
}
Даже лучше:
Переопределите метод toString() как в Guest, так и в VIPGuest.
Последний вызывает super.toString() и добавляет дополнительную информацию.
g является ссылкой типа Guest, поэтому вы можете получить доступ только к членам Gusest из него. Если вы хотите получить доступ к членам VIPGuest, вам придется явно понизить его. Например.:
VIPGuest vg = (VIPGuest) g;
writer.write(g.getGuestID() + "," +
g.getFName() + "," +
g.getLName() + "," +
g.getDateJoin() + "," +
vg.getVIPstartDate() + "," +
vg.getVIPexpiryDate());
Это должно работать, но это плохой дизайн, он вынуждает ваш метод saveGuestsData хорошо знать ваши реализации Guest. Более надежный дизайн состоит в том, чтобы перенести эту логику в классы Guest и заставить этот метод просто вызывать их:
public class Guest {
@Override
public String toString() {
return getGuestID() + "," + getFName() + "," + getLName() + "," + g.getDateJoin();
}
// other methods...
}
public class VIPGuest extends Guest {
@Override
public String toString() {
return super.toString() + ", " + getVIPstartDate() + "," + getVIPexpiryDate());
// other methods...
}
А затем просто вызовите этот метод:
for (Guest g : guests) {
writer.write(g.toString());
}
gявляется гостем, а не VIP-гостем. Если вы хотите использовать методы класса VIPGuest, вам нужно привестиgк VIPGuest, например.((VIPGuest)g).getVIPstartDate()