Java 访问子类的属性

Java 访问子类的属性,java,inheritance,compiler-errors,iteration,Java,Inheritance,Compiler Errors,Iteration,我对Java非常陌生,我很难理解为什么我总是在命令行中出错。我有一个超类Guest,带有变量guestID、fName、lName和dateJoin。我还有一个子类VIPGuest,它带有附加变量VIPstartDate和VIPexpiryDate 我有一个ArrayList guests,它保存我记录中的所有来宾对象。我希望遍历ArrayList并将每个来宾写入一个文本文件,每个来宾都以guestID、fName、lName、dateJoin的形式出现在新行中,并用逗号分隔(如果来宾是VIPG

我对Java非常陌生,我很难理解为什么我总是在命令行中出错。我有一个超类Guest,带有变量guestID、fName、lName和dateJoin。我还有一个子类VIPGuest,它带有附加变量VIPstartDate和VIPexpiryDate

我有一个ArrayList guests,它保存我记录中的所有来宾对象。我希望遍历ArrayList并将每个来宾写入一个文本文件,每个来宾都以guestID、fName、lName、dateJoin的形式出现在新行中,并用逗号分隔(如果来宾是VIPGuest,则使用guestID、fName、lName、dateJoin、VIPstartDate、VIPexpiryDate)

我的代码如下。当我使用类似的代码为一个没有子类的类的对象的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;
          }
  }

在这个答案中,我假设
VIPGuest
扩展了
Guest

在常规
Guest
上使用任何
VIPGuest
方法之前,您需要将Guest强制转换为VIPGuest

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
实际上是一个VIPGuest,但您对它的引用仅限于一位来宾


请注意,如果
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());
}
更好的是:

覆盖
Guest
VIPGuest
中的方法
toString()


后者调用
super.toString()
并添加附加信息。

g
是类型为
Guest
的引用,因此您只能从中访问
Guest
的成员。如果要访问
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
是客人,不是客人。如果要在VIPGuest类上使用方法,需要将
g
强制转换为VIPGuest——例如
((VIPGuest)g)。getVIPstartDate()
修复了它!谢谢:)@Habilee我建议你使用IDE,它会向你解释这种错误。我正要发布一个类似的答案;)