编辑:这完全是我的错误,可能是因为凌晨4点匆匆忙忙。代码在技术上是合理的并且工作正常,但是感谢评论我删除了一些冗余以使事情变得更聪明。
我正在开发一个处理Java超级/子类和继承的类项目。虽然90%的代码工作得很好,但是一件小事似乎并不想工作,我有点为什么感到困惑。基本上,我们正在创建一个名为CompactDisc的新类,其中包含产品代码,描述,价格和艺术家等信息。当用户输入适当的代码(sgtp)时,控制台将输出信息。不幸的是,尽管给出了数据,艺术家系列总是空白的。虽然这个项目涉及其他课程,但我只会发布我认为重要的课程。
ProductApp.java:
import java.util.Scanner;
public class ProductApp
{
public static void main(String args[])
{
// display a weclome message
System.out.println("Welcome to the Product Selector\n");
// perform 1 or more selections
Scanner sc = new Scanner(System.in);
String choice = "y";
while (choice.equalsIgnoreCase("y"))
{
System.out.print("Enter product code: ");
String productCode = sc.next(); // read the product code
sc.nextLine(); // discard any other data entered on the line
// get the Product object
Product p = ProductDB.getProduct(productCode);
// display the output
System.out.println();
if (p != null)
System.out.println(p.toString());
else
System.out.println("No product matches this product code.\n");
System.out.println("Product count: " + Product.getCount() + "\n");
// see if the user wants to continue
System.out.print("Continue? (y/n): ");
choice = sc.nextLine();
System.out.println();
}
}
}
Product.java:
import java.text.NumberFormat;
public class Product
{
private String code;
private String description;
private String artist;
private double price;
protected static int count = 0;
public Product()
{
code = "";
description = "";
price = 0;
}
public void setCode(String code)
{
this.code = code;
}
public String getCode(){
return code;
}
public void setArtist(String artist)
{
this.artist = artist;
}
public String getArtist(){
return artist;
}
public void setDescription(String description)
{
this.description = description;
}
public String getDescription()
{
return description;
}
public void setPrice(double price)
{
this.price = price;
}
public double getPrice()
{
return price;
}
public String getFormattedPrice()
{
NumberFormat currency = NumberFormat.getCurrencyInstance();
return currency.format(price);
}
@Override
public String toString()
{
return "Code: " + code + "\n" +
"Description: " + description + "\n" +
"Price: " + this.getFormattedPrice() + "\n";
}
public static int getCount()
{
return count;
}
}
CompactDisc.java:
public class CompactDisc extends Product
{
private String artist;
public CompactDisc()
{
super();
artist = "";
count++;
}
@Override
public void setArtist(String artist)
{
this.artist = artist;
}
@Override
public String getArtist(){
return artist;
}
@Override
public String toString()
{
return super.toString() +
"Artist: " + artist + "\n";
}
}
ProductDB.java:
public class ProductDB
{
public static Product getProduct(String productCode)
{
// In a more realistic application, this code would
// get the data for the product from a file or database
// For now, this code just uses if/else statements
// to return the correct product data
Product p = null;
if (productCode.equalsIgnoreCase("java") ||
productCode.equalsIgnoreCase("jsps") ||
productCode.equalsIgnoreCase("mcb2"))
{
Book b = new Book();
if (productCode.equalsIgnoreCase("java"))
{
b.setCode(productCode);
b.setDescription("Murach's Beginning Java");
b.setPrice(49.50);
b.setAuthor("Andrea Steelman");
}
else if (productCode.equalsIgnoreCase("jsps"))
{
b.setCode(productCode);
b.setDescription("Murach's Java Servlets and JSP");
b.setPrice(49.50);
b.setAuthor("Andrea Steelman");
}
else if (productCode.equalsIgnoreCase("mcb2"))
{
b.setCode(productCode);
b.setDescription("Murach's Mainframe COBOL");
b.setPrice(59.50);
b.setAuthor("Mike Murach");
}
p = b; // set Product object equal to the Book object
}
else if (productCode.equalsIgnoreCase("txtp"))
{
Software s = new Software();
s.setCode("txtp");
s.setDescription("TextPad");
s.setPrice(27.00);
s.setVersion("4.7.3");
p = s; // set Product object equal to the Software object
}
else if (productCode.equalsIgnoreCase("sgtp"))
{
CompactDisc c = new CompactDisc();
c.setCode("sgtp");
c.setDescription("Sgt. Pepper's Lonely Hearts Club Band");
c.setPrice(15.00);
c.setArtist("The Beatles");
p = c; // set Product object equal to the CompactDisc object
}
return p;
}
输出。如你所见,艺术家是空的:
Welcome to the Product Selector
Enter product code: sgtp
Code: sgtp
Description: Sgt. Pepper's Lonely Hearts Club Band
Price: $15.00
Artist:
Product count: 1
Continue? (y/n):
我有预感我在ProductDB.java中做错了什么,但我可能错了。提前谢谢。
答案 0 :(得分:1)
我无法重现您的错误。我得到了结果:
Welcome to the Product Selector
Enter product code: sgtp
Code: sgtp
Description: Sgt. Pepper's Lonely Hearts Club Band
Price: 15,00 €
Artist: The Beatles
Product count: 1
Continue? (y/n):
Product
的艺术家字段被CompactDisk
隐藏。你应该真的改变它以拥有合理的设计。但我不明白为什么这不起作用。
答案 1 :(得分:0)
产品确实不应该是artist
字段,也不应该是setArtist()
。
这里发生的是你可以覆盖一个方法,但你不能覆盖一个字段,只需隐藏它。当您访问字段时,它取决于引用的类型,而不是对象的实际类。由于artist
字段中没有任何内容在构建它时被CompactDisk
隐藏,因此您将获得一个空字段。
答案 2 :(得分:0)
由于声明
,您的问题仍然存在 Product p
后来成了
Product p = new CompactDisc();
该行表示,您的变量仍然引用类型Product
和CompactDisc
更改
@Override
public String toString()
{
return super.toString() +
"Artist: " + artist + "\n";
}
到
@Override
public String toString()
{
return super.toString() +
"Artist: " + this.getArtist() + "\n";
}
当您打印变量时,它仍指向声明的LHS,当您访问方法时,它属于RHS。
作为旁注,你有一个设计问题(评论相同的早期)以及在父母和孩子中有多个艺术家变量。在一个级别删除它,使您的程序更清晰。
答案 3 :(得分:0)
由于p
是具有Product
字段的artist
,因此当您调用toString
方法时,您将获得其artist
中包含的值} field,这是空字符串。
这主要是因为您无法覆盖字段。你是hiding the child field with the parent field。
在子类中,超类中的字段不能通过其简单名称引用,父类也是如此。
由于您没有以奇怪的方式在artist
中使用Product
,我建议您在Product
类中删除它并使用CompactDisk
。