我应该修改程序以在GUI中显示输出。除了一个字段外,这大部分都是完成的。我无法显示的唯一字段是'重新进货费',它位于DVD
的子类中。 Inventory
是主要类,然后DVD
类和MovieTitle
是DVD
的子类。除restockingFee
子类中的MovieTitle
外,一切都正确显示。例外是:
Exception in thread "main" java.lang.ClassCastException: inventoryProgram3.DVD cannot be cast to inventoryProgram3.MovieTitle
at inventoryProgram3.Inventory.myRedraw(Inventory.java:204)
at inventoryProgram3.Inventory.<init>(Inventory.java:149)
at inventoryProgram3.Inventory.main(Inventory.java:156)
如何从子类调用restockfee方法?
这是Inventory
类:
package inventoryProgram4;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
@SuppressWarnings("serial")
public class Inventory extends JFrame implements ActionListener {
// declare instance attributes
private final JPanel buttonJPanel;
private final JPanel areaJPanel;
private final JButton buttons[];
private final BorderLayout layout;
private final Container pane;
private final JLabel l0;
private final JLabel l1;
private final JLabel l2;
private final JLabel l3;
private final JLabel l4;
private final JLabel l5;
private final JLabel totalInv;
// Text fields
static private JTextField t0;
static private JTextField t1;
static private JTextField t2;
static private JTextField t3;
static private JTextField t4;
static private JTextField t5;
static private JTextField totalInvValue;
static private DVD rb[];
static private int index;
static private DVD[] DVD;
public Inventory() { // constructor
super("DVD Inventory");
DVD = new DVD[5];
DVD[0] = new DVD("1", " Fast and Furious 6", 10, 15);
DVD[1] = new DVD("2", " The Matrix Reloaded", 8, 5);
DVD[2] = new DVD("3", " In Pursuit of Happiness", 8, 5);
DVD[3] = new DVD("4", " Darknet", 8, 5);
DVD[4] = new DVD("5", " Goonies", 8, 5);
DVD = sortDVD(DVD);
rb = DVD;
index = 0;
// setting layout
layout = new BorderLayout(25, 15);
setLayout(layout);
// getting pane
pane = getContentPane();
// set up areaJPanel
areaJPanel = new JPanel();
areaJPanel.setLayout(new GridLayout(0, 2));
// create area components
l0 = new JLabel(" DVD Title: ");
l1 = new JLabel(" Title Name: ");
l2 = new JLabel(" DVD's in Stock: ");
l3 = new JLabel(" DVD Price: ");
l4 = new JLabel(" Restock Fee: ");
l5 = new JLabel(" Inventory value: ");
totalInv = new JLabel(" Value of entire inventory: ");
totalInvValue = new JTextField(10);
totalInvValue.setEditable(false);
t0 = new JTextField(15);
t0.setEditable(false); // making text box non editable
t1 = new JTextField(15);
t1.setEditable(false);
t2 = new JTextField(10);
t2.setEditable(false);
t3 = new JTextField(10);
t3.setEditable(false);
t4 = new JTextField(10);
t4.setEditable(false);
t5 = new JTextField(10);
t5.setEditable(false);
// adding components
areaJPanel.add(l0); // n x 2 grid: label - textfield
areaJPanel.add(t0);
areaJPanel.add(l1);
areaJPanel.add(t1);
areaJPanel.add(l2);
areaJPanel.add(t2);
areaJPanel.add(l3);
areaJPanel.add(t3);
areaJPanel.add(t4);
areaJPanel.add(l4);
areaJPanel.add(t4);
areaJPanel.add(l5);
areaJPanel.add(t5);
areaJPanel.add(totalInv);
areaJPanel.add(totalInvValue);
// Adding four buttons: first, next, previous, last
// create array of buttons, size 4
buttons = new JButton[4];
// create a JPanel for the buttons
buttonJPanel = new JPanel();
// set panel layout to 1 row and columns = size of array
buttonJPanel.setLayout(new GridLayout(1, buttons.length));
// adding button "next"
buttons[1] = new JButton("Previous"); // instantiate button "next"
buttons[1].setActionCommand("Previous"); // identifies the action event
buttons[1].addActionListener(this); // add an action listener for button
buttonJPanel.add(buttons[1]); // add button to the button JPanel
// adding button "previous"
buttons[2] = new JButton("Next"); // instantiate button "previous"
buttons[2].setActionCommand("next"); // identifies the action event
buttons[2].addActionListener(this); // add an action listener for button
buttonJPanel.add(buttons[2]); // add button to the button JPanel
pane.add(buttonJPanel, BorderLayout.SOUTH); // place buttons at bottom of pane
pane.add(areaJPanel, BorderLayout.WEST);
myRedraw(); // showing first item
}// end constructor
public static void main(String args[]) {
// creating frame
Inventory panelFrame = new Inventory();
// close the frame on clicking X button
panelFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// setting size
panelFrame.pack();
// setting visibility
panelFrame.setVisible(true);
}// end main method
static DVD[] sortDVD(DVD[] DVD) {
int in, out, NumOfEle = DVD.length;
for (out = 1; out < NumOfEle; out++) {
DVD temp = DVD[out];
in = out;
while (in > 0 && DVD[in - 1].getTitle().compareTo(temp.getTitle()) > 0) {
DVD[in] = DVD[in - 1];
--in;
}
DVD[in] = temp;
}
return DVD;
}
private static double calculateEntireInventory(DVD[] DVD1) {// method to return inventory total
double totalInventory = 0;
for (DVD DVD : DVD1) {
totalInventory += (DVD.getInventoryValue());
}
return totalInventory;
}
// method to display contents
static void myRedraw() {
// currency formatter
NumberFormat nf = new DecimalFormat("$#,##0.00");
// reference to object under consideration
DVD f = (DVD) rb[index];
double inventoryValue = f.getInventoryValue();
// set values for indicated object attribute
t0.setText(f.getTitle()); // item name
t1.setText(f.getItem() + ""); // item number
t2.setText(f.getStock() + ""); // item quantity
t3.setText(nf.format(f.getPrice())); // item price
// Problem here
/**
* Exception in thread "main" java.lang.ClassCastException: inventoryProgram3.DVD cannot be
* cast to inventoryProgram3.MovieTitle at
* inventoryProgram3.Inventory.myRedraw(Inventory.java:204) at
* inventoryProgram3.Inventory.<init>(Inventory.java:149) at
* inventoryProgram3.Inventory.main(Inventory.java:156)
**/
MovieTitle t = (MovieTitle) f;
t4.setText(nf.format(t.getRestockingFee())); // item re-stocking fee
// up above
t5.setText(nf.format(inventoryValue));
// up above
// total value of inventory
totalInvValue.setText(nf.format(calculateEntireInventory(DVD)));
}// end method
// action handler for button presses
public void actionPerformed(ActionEvent event) {
int last = rb.length - 1;
// get command string assigned to the pressed button.
String action = event.getActionCommand();
// set index based on which button was pressed.
if (action.equals("prev")) { // previous pressed
if (index == 0) {
index = last; // at first item, go to last item
} else {
--index; // go to previous item
}
} else {// next pressed
if (index == last) {
index = 0; // at last item, go to first time
} else {
++index; // go to next item
}
}
myRedraw();
}// end method
} // end program
这是DVD
类:
package inventoryProgram3;
class DVD {
// Create local variable to capture data from parameter list of the constructor
private String thisItem;
private String thisTitle;
private double thisStock;
private double thisPrice;
// Create constructor to call this class from external classes
public DVD(String item, String title, double stock, double price) {
// Set local variables to values passed in via a class call
thisItem = item;
thisTitle = title;
thisStock = stock;
thisPrice = price;
} // end constructor
// getInventoryValue: calculates the total value of the inventory for the item
public double getInventoryValue() {
return getPrice() * getStock();
}
// set name
public void setTitle(String title) {
thisTitle = title;
}// end method setTitle
// return Title
public String getTitle() {
return thisTitle;
}// end method getTitle
// set Stock
public void setStock(double stock) {
thisStock = stock;
}// end method setStock
// return Stock
public double getStock() {
return thisStock;
}// end method get Stock
public void setPrice(double price) {
thisPrice = price;
}// end method setPrice
// return Price
public double getPrice() {
return thisPrice;
}// end method getPrice
public void setItem(String item) {
thisItem = item;
}// end method setItem
// return Item
public String getItem() {
return thisItem;
}// end method getItem
// calculate the inventory value
public double value() {
return thisPrice * thisStock;
}// end method value
}// end class
这是MovieTitle
类:
package inventoryProgram3;
public class MovieTitle extends DVD {
private final double restockingFee = 0.05;
public MovieTitle(String item, String title, double stock, double price) {
super(item, title, stock, price);
}
public double getRestockingFee() {
return getPrice() * restockingFee;
}
}
答案 0 :(得分:3)
您不能将超类对象强制转换为其子类之一,只允许反向。它看起来最简单的方法来修复你现在拥有的是将数组声明为类型为child并在主程序中使用子对象填充它,然后你可以访问子类和超类方法。
答案 1 :(得分:3)
异常表示出了什么问题。您正在尝试将DVD投射到MovieTitle。尝试绘制自己的维恩图。所有MovieTitles都是DVD,但不是所有的DVD都是MovieTitles。例外情况表明您正在尝试处理其中一个DVD - 这些不是电影的标题,就像它是一个MovieTitle一样。
最初的猜测是您直接实例化DVD。您可以通过阅读代码来确认这一点,以查看实例化对象的位置。您需要将对象实例化为MovieTitle而不是DVD,或者您需要使用DVD方法来获取DVD的标题。
答案 2 :(得分:0)
显示错误是因为您正在将DVD投射到MovieTitle。 DVD不是MovieTtitle对象,因此您无法像这样投射它。
restockFee是MovieTitle的更具体的价格。
试试这个,看它是否有效:
在MovieTitle类中:
@Override
public double getPrice {
return super.getPrice() * restockingFee;
}
在库存类:
//MovieTitle t = (MovieTitle) f;
//t4.setText(nf.format(t.getRestockingFee())); // item re-stocking fee
t4.setText(nf.format(f.getPrice()); // item re-stocking fee
答案 3 :(得分:0)
您应该采用naming convention,像DVD = new DVD[5]
这样的代码很难阅读。
关于你的问题,将超类实例强制转换为它的子类是没有意义的。
让我们假设演员成功了。由于超类不具有子类中定义的状态,因此在调用子类方法时,结果与子类中定义的字段一起使用会产生什么结果?这些字段不存在于您执行强制转换的超类对象中。在您的示例中,restockingFee
实例中没有DVD
,那么您会得到什么?
在允许使用此语言的语言中,如C语言系列,您将获得DVD
对象边界之后的任何内存内容(换句话说,您将有一个错误)。 Java会保护您免受此错误的影响并抛出ClassCastException
。
您的问题有很多可能的解决方案:
1)将您需要的状态/方法移动到超类。在您的示例中,如果您始终在restockingFee
上使用DVD
,请将其移至DVD
类。
2)如果restockingFee
仅在子类中有意义(似乎是您的用例),并且您同时使用超类和子类实例,那么只有在使用子类实例时才需要读取它:
if (f instanceof MovieTitle) {
MovieTitle t = (MovieTitle) f;
t4.setText(nf.format(t.getRestockingFee()));
}
3)如果您只使用子类实例,那么将相关字段声明为子类类型并完全避免转换(以这种方式获得编译时安全性,避免您遇到的运行时错误):
static private MovieTitle rb[];
4)使用不兼容接口时,更复杂设计的一般解决方案是Adapter模式。
答案 4 :(得分:0)
我终于找到了答案,即使我真的不明白,我正在查看其他代码并尝试了不同的东西。我在带有数组的主类中的原始代码:
public Inventory() { // constructor
super("DVD1");
DVD = new DVD[7];
DVD[0] = new DVD ( "1", " Fast and Furious 6", 10, 15 );
DVD[1] = new DVD ( "2", " The Matrix Reloaded", 8, 5 );
DVD[2] = new DVD ( "3", " In Pursuit of Happiness", 8, 5 );
DVD[3] = new DVD ( "4", " Darknet", 8, 5 );
DVD[4] = new DVD ( "5", " Goonies", 8, 5 );
public Inventory() { // constructor
super("DVD1");
DVD = new DVD[7];
DVD[0] = new DVD ( "1", " Fast and Furious 6", 10, 15 );
DVD[1] = new DVD ( "2", " The Matrix Reloaded", 8, 5 );
DVD[2] = new DVD ( "3", " In Pursuit of Happiness", 8, 5 );
DVD[3] = new DVD ( "4", " Darknet", 8, 5 );
DVD[4] = new DVD ( "5", " Goonies", 8, 5 );
现在更改为并且工作原理是:
I added in the last two to the array and added two more buttons (first and last) to make sure the buttons worked. With changing the new DVD to new MovieTitle, the restockFee does show up in GUI. Yes, I also needed:
public Inventory() { // constructor
super("DVD1");
DVD = new DVD[7];
DVD[0] = new MovieTitle ( "1", " Fast and Furious 6", 10, 15 );
DVD[1] = new MovieTitle ( "2", " The Matrix Reloaded", 8, 5 );
DVD[2] = new MovieTitle ( "3", " In Pursuit of Happiness", 8, 5 );
DVD[3] = new MovieTitle ( "4", " Darknet", 8, 5 );
DVD[4] = new MovieTitle ( "5", " Goonies", 8, 5 );
DVD[5] = new MovieTitle ( "6", " zzzz", 8, 5 );
DVD[6] = new MovieTitle ( "7", " AAaaaa", 15, 19.99 );
</code>