[英]Class A instantiates a Class B instance. How can the Instance of ClassB call a method of class A?
[英]If an instance of class B is a member of class A, how can class B call a method of class A when a button in class B is pressed?
我正在嘗試使用MVC編碼實踐來制作GUI來為桌面RPG生成字符。 我將有幾個“控制面板”類,每個類都有一組特定的按鈕來處理角色創建過程的不同方面(滾動屬性,購買設備等)。 我的Controller類將每個“控制面板”類的實例作為成員。 我的通用代碼在這里:
公共類控制器{
private Model m; //class Model not shown
private Viewer v; //class Viewer not shown
private JFrame frame;
private ControlPanelOne cpo;
private ControlPanelTwo cpt; //class ControlPanelTwo not shown
public Controller(){
m = new Model();
v = new Viewer();
frame = new JFrame();
frame.setLayout(…);
cpo = new ControlPanelOne();
cpt = new ControlPanelTwo();
frame.add(cpo.getPanel());
frame.add(cpt.getPanel());}
public void update(){
m.update();
v.update();}}
公共類ControlPanelOne {
private JPanel panel;
private JButton button;
public ControlPanelOne(){
panel = new JPanel();
button = new JButton(“press me”);
panel.add(button);
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//do some stuff;
//call Controller’s update method;}})} //the important bit!
public JPanel getPanel(){
return panel;}}
公共課程測試人員{
public static void main(String[] args){
Controller c = new Controller();}}
當按下ControlPanelOne的按鈕時,如何獲取ControlPanelOne以查看並調用Controller的update()方法?
我嘗試使ControlPanelOne擴展Controller,以便在按下ControlPanelOne的按鈕時可以調用super.update(),但是隨后實例化Controller時(例如在Tester類中),其ControlPanelOne成員也被實例化,由此Controller和ControlPanelOne的構造函數被稱為構造的無限循環。
試圖通過將Controller的update()方法設置為靜態來欺騙編譯器是行不通的,因為實例m和v不是靜態的。
如果可以幫助,我不想使ControlPanelOne成為Controller的內部類。 還會有其他“控制面板”類(ControlPanelTwo等),而且恐怕使它們成為所有內部類都會使Controller的代碼冗長而混亂。 我希望每個“控制面板”作為一個單獨的類來處理一個特定的功能,以保持整潔,並易於維護和模塊化代碼重用。
顯然,ControlPanelOne不應將Controller作為成員變量,因為a)從概念上講是向后的,並且b)其他“控制面板”的實例將需要自己的Controller實例…
我曾經讓Controller擴展JFrame和ControlPanelOne擴展JPanel(以便Controller可以直接add()ContollPanelOne的實例,而不是調用ControlPanelOne的getPanel()方法),但我讀到使類擴展此類組件而不是使此類組件成為您的組件成員。班級形式差。 但是如果能以某種方式幫助回到Controller和ControlPanelOne擴展JFrame和JPanel的話……
也許我對MVC的想法是錯誤的...
請指教
確實,您沒有遵循MVC模式。 該模式的要旨是提供模型,視圖和控制器的清晰分隔。 因此,任何相互繼承或組合的嘗試都將使利益喪失。
我要做的是使AbstractAction
像這樣:
public class UpdateAction extends AbstractAction {
private Controller controller;
...
@Override
public void actionPerformed(ActionEvent ae) {
controller.update();
}
}
然后,初始化並在視圖外部設置按鈕,該視圖無需知道其顯示內容。 它只需要知道它的工作就是展示東西。 您可以讓控制器extend JFrame
並將JPanel
添加到其中。
JButton button = new JButton("Button");
button.setAction(new UpdateAction(this));
... more button set up
... add button to views
... add views to frame
現在,每當單擊按鈕時,它將調用控制器的update()
方法。
當按下ControlPanelOne的按鈕時,如何獲取ControlPanelOne以查看並調用Controller的update()方法?
通常,這是通過使用觀察者模式來實現的 ,其中控制器將在某些事件發生時向要注冊的視圖注冊興趣,視圖將在事件發生時在適當時調用每個注冊方。 這樣,視圖就不在乎控制器,而只在乎它需要生成適當的事件。
如果我很好理解B類是A類的組成部分
B類不知道類A,即使它是該類的成員,也沒有對其的引用。 這稱為合成是一種“具有”關系。 如果您想了解該類,則還應該在類B中有一個類A的實例,或者將類A的方法設為靜態。
class B {
btnPressed() {
/*To call this method you need or an object of class A, or static method in class A*/
methodA(); //Method form class A
op1:
a = new A();
a.methodA();
op2:
//make methodA static in class A
A.methodA();
}
}
class A {
b = new B();
methodA();
}
希望這可以幫助。
您的直接目標是在ControlPanelOne
的構造函數中匿名實現的ActionListener
的actionPerformed
方法內的Controller
實例上調用update
。 ControlPanelOne
由Controller
實例的構造函數組成。 實際上,您需要從Controller
到ControlPanelOne
的循環引用,反之亦然。
這是一個簡單的方法。 您可以在此處簽出最少工作的項目。
首先,您的Controller
。
public class Controller {
private Model m; //class Model not shown
private Viewer v; //class Viewer not shown
private JFrame frame;
private ControlPanelOne cpo;
private ControlPanelTwo cpt; //class ControlPanelTwo not shown
public Controller() {
m = new Model();
v = new Viewer();
frame = new JFrame();
frame.setLayeredPane(null); // Do something
cpo = new ControlPanelOne(this); // Supply self to the instance of ControlPanelOne
cpt = new ControlPanelTwo();
frame.add(cpo.getPanel());
frame.add(cpt.getPanel());
}
public void update() {
m.update();
v.update();
}
}
接下來, ControlPanelOne
:
public class ControlPanelOne {
private JPanel panel;
private JButton button;
public ControlPanelOne(final Controller controller){
panel = new JPanel();
button = new JButton("press me");
panel.add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//do some stuff;
controller.update();
}
});
}
public Component getPanel() {
return null;
}
}
要記住的重要事情是在構造函數中聲明Controller
final提供的實例(您可以在此處找到原因)。 在Java 8中,這不是必需的,但是仍然是習慣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.