2015-06-27 68 views
0

我應該修改程序來在GUI中顯示輸出。這主要是完成,除了一個領域。我無法展示的唯一領域是「補貨費」,它在DVD的子類中。 Inventory是主類,那麼DVD類和MovieTitleDVD的子類。除了MovieTitle子類中的restockingFee之外,所有內容都可以正確顯示。例外情況是:如何將對象轉換爲不從其繼承的類型?

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

可能重複http://stackoverflow.com/問題/ 4862960 /從超級類到子類的顯式投射) – Madhan

回答

3

你不能投一個超類對象其中一個孩子,只有相反是允許的。它看起來是最簡單的方法來解決你目前所擁有的是將數組聲明爲child類型,並在主程序中用子對象填充它,然後可以訪問子類和超類方法。

3

異常表示出了什麼問題。您正試圖將DVD投射到MovieTitle。嘗試繪製自己的維恩圖。所有的MovieTitles都是DVD,但並非所有的DVD都是MovieTitles。例外情況表明,您正在試圖處理其中一個DVD--即不是電影標題,就好像它是一個MovieTitle。

最初的猜測是你直接實例化了DVD。您可以通過閱讀代碼來確認這一點,以查看實例化對象的位置。無論是需要將對象實例化爲MovieTitle而不是DVD,還是需要使用DVD的方法來獲取DVD的標題。

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 
+0

謝謝大家,我不太清楚它的意思,但我正在努力。這裏的建議幫助了很多。 – James

0

您應該採取naming convention,像DVD = new DVD[5]代碼非常難以閱讀。

關於你的問題,將一個超類實例投射到它的子類是沒有意義的。

讓我們假設演員成功。由於超類沒有在子類中定義的狀態,因此調用與子類中定義的字段一起使用的子類方法時會出現什麼結果?這些字段不存在於您執行轉換的超類對象中。在你的例子中,DVD實例中沒有restockingFee,那麼你會得到什麼?

在允許這樣做的語言中,比如C族語言,你會得到任何內存緊跟在DVD對象的邊界之後(換句話說,你會有一個bug)。 Java可以保護你免受這個bug的侵害,並拋出ClassCastException

有一些對您的問題可能的解決方案:

1)將需要進行超國家/方法。在你的例子中,如果你總是在DVD上使用restockingFee,移動它到DVD類。

2)如果restockingFee僅在子類是有道理的(好像是你的使用情況),並同時使用超和子類的實例,那麼你需要閱讀它,只有當你的子類的實例工作:

if (f instanceof MovieTitle) { 
    MovieTitle t = (MovieTitle) f; 
    t4.setText(nf.format(t.getRestockingFee())); 
} 

3)如果您有子類的實例只工作,然後宣佈相關領域是子類型,並且完全避免了投(你編譯時安全通過這種方式,避免了你所面對的運行時錯誤):

static private MovieTitle rb[]; 

4)Gen當您使用不兼容的接口時,更復雜的設計的解決方案是Adapter模式。

+0

我仍然習慣於命名約定,我幾乎完成了我的第一個Java類(學期),還有很多東西需要學習,我在這些空閒時間裏做了什麼計劃。至於把子類方法放在超類中,我希望能夠讓我更容易,但那不是任務。 – James

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 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> 

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:

if (f instanceof MovieTitle) { MovieTitle t = (MovieTitle) f;
t4.setText(nf.format(t.getRestockFee())); // item re-stocking fee }

[從超類的子類顯式類型轉換(的
相關問題