2015-05-08 10 views
0

Я делаю игру, и я пытаюсь избавиться от всей избыточности в моем коде. Все мои панели (PlayPanel, HighScore, Quit, ..) имеют много общих свойств, поэтому я сделал класс IPanel для распространения на всех моих панелях. это выглядит следующим образом:Могу ли я использовать код из одного класса (конструктор + методы) в другом классе? (java)

package menu; 

import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.ImageIcon; 
import javax.swing.JPanel; 

public class IPanel extends JPanel implements ActionListener{ 

    public Image achtergrond; 
    public Tanks mainVenster; 

    public String backgroundPath; 



    public IPanel(String backgroundPath, Tanks mainVenster) 
    {  
     super(); 
     this.mainVenster = mainVenster; 
     this.setLayout(null); 

     this.backgroundPath = backgroundPath; 
     achtergrond = new  //achtergrond is dutch for background 
      ImageIcon(getClass().getResource(backgroundPath)).getImage(); 

    } 

    public void paintComponent(Graphics g) 
    { 
      super.paintComponent(g); 
      g.drawImage(achtergrond, 0, 0, this.getWidth(), this.getHeight(), 
       this); 
    } 


    public void actionPerformed(ActionEvent ae) 
    { 
     mainVenster.switchPanel(); 
    } 

    public void switchPanel(Tanks toActivate) 
    { 
     remove(mainVenster); 
     mainVenster = toActivate; 
     add(mainVenster); //this is wrong, no idea what to do actually 

     validate(); 
     repaint(); 
    } 

    } 

Я могу использовать конструктор в других классах, но я не знаю, как использовать paintComponent и actionPerformedметодов в других классах. Я использую эти 2 метода во всех своих панелях, поэтому считаю, что нет необходимости снова писать методы для всех этих панелей.

пример одного из моих панелей QuitPanel:

package menu; 

import java.awt.Color; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 



@SuppressWarnings("serial") 
public class QuitPanel extends JPanel implements ActionListener 
{ 

    public Button yesKnop, noKnop; 
    public JLabel label; 
    public Tanks mainVenster; 
    public QuitPanel quitPanel; 

    public IPanel quit; 


    public QuitPanel(Tanks mainVenster) 
    { 

     quit = new IPanel("/achtergronden/menu.jpg", mainVenster); 

     int x = 95, width = 200, height = 50; 

     label = new JLabel("ARE YOU SURE?"); 
     Font font = new Font("Courier", Font.BOLD, 25); 
     label.setFont(font); 
     label.setBounds(x+20, 400, width, height); 

     yesKnop = new Button("/buttons/YES.png",x, 450, this);  
     noKnop = new Button("/buttons/NO.png",x, 525, this); 

     this.add(quit); 
     this.add(label); 
     this.add(noKnop); 
     this.add(yesKnop); 

    } 


    public void actionPerformed(ActionEvent ae) 
    { 
     if(ae.getSource() == noKnop) 
      quit.switchPanel(mainVenster); //this is wrong 
     else if(ae.getSource() == yesKnop) 
      System.exit(0); 

    } 

} 

, как вы можете видеть, я расширил класс с JPanel, потому что, когда я пытался продлить IPanel я получил ошибку при public HTPPanel(Tanks mainVenster), что сказал the error

Когда я открываю свой quitPanel, я получаю это: quitPanel when opened

, так что я знаю, что должно быть частью моего кода правильной, единственная проблема заключается в том, что мой фон не загружается -> (public void paintComponent(Graphics g) метод)

вопрос является: как я используйте метод i, созданный в классе nr 1 в классе nr 2?

кроме того, NoButton не работает (yesButton работает нормально) -> (public void actionPerformed(ActionEvent ae) метод) -> также из-за public void switchPanel(Tanks toActivate) я думаю,

спасибо так много!

ответ

3

Да, вы можете, и есть два обобщенных подхода, состав и interhitence.

С составом вы вводите код в новый класс, который затем использует ваше текущее решение, создавая и удерживая экземпляр класса, поддерживающего код.

С наследованием вы создаете класс, который расширяет ваше текущее решение, и поместите код в метод в этом родительском классе. Тогда у вас есть «другой» класс, расширяющий тот, который содержит желаемый код.

Вообще, композиция легче обрабатывать со временем, чем наследование; но со временем вы узнаете, что наследование является лучшим решением из-за его способности использовать полиморфизм.

0

вы должны добавить конструктор по умолчанию без параметров в класс IPanel, например.

public IPanel() { } 

, то вы можете использовать свой родительский класс IPanel для расширения.

+0

это кажется разумным ответом, но я действительно не понимаю, как я могу вызвать конструктор без параметров, которые я хочу ... – Lola

1

Ошибка в том, что при продлении IPanel вы должны использовать хотя бы один из конструкторов super. В этом случае, есть одна, так что вам придется использовать:

public IPanel(String backgroundPath, Tanks mainVenster) 

поправочных

Это не обязательно, что вы потребность в (кажется идеальным для меня), но в конструктор, один из конструкторов superclass's необходимо вызвать с помощью super(...).

Значение, если бы я был класс A с конструктором:

public class A { 
    public A(String name) { 
    } 
} 

и класса B extends A, я мог бы сделать несколько вещей:

public class B { 
    // Option 1: Superclass's Constructor 
    public B(String name) { 
     super(name); 
    } 

    // Option 2: Pass static value 
    public B() { 
     super("something here"); 
    } 

    // Option 3: Use null 
    public B() { 
     super(null); 
    } 
} 

Независимо от того, что, в конце концов, если ваш superclass содержит только constructors с parameters, каждый constructor подкласса должен будет позвонить super(...) в один из superclass's constructors.

Если поставить по умолчанию constructor т.д .: public A() {} в вашем superclass, вам не нужно будет вызывать super() на любом из них.

0

Если вы укажете конструктор, компилятор не будет создавать для вас конструктор без параметров (вы сделали это в своем классе IPanel).

public class A { 
    public A(String str) { 
     //Compiler will not create a constructor without parameters. 
    } 
} 

Перевернутый, если вы не укажете конструктор, компилятор собирается создать конструктор без параметров для вас (вы сделали это в своем классе HTPPanel).

public class A { 
    //Compiler will create a constructor without parameters. 
} 

Теперь дело в том, что в классе, который проходит какой-то другой класс, конструктор по умолчанию будет вызывать его конструктор суперкласса без аргументов.

public class A { 
    public A(String str) {} 
} 

public class B extends A {} 

public class C { 
    public static void main(String[] args) { 
     B b = new B(); //Compile error 
    } 
} 

Но также, если вы укажете конструктор в классе B, но не добавить вызов это конструктор суперкласса, компилятор автоматически вызывает конструктор суперкласса без аргументов.

public class A { 
    public A(String str) {} 
} 

public class B extends A { 
    public B(int i) {} 
} 

public class C { 
    public static void main(String[] args) { 
     B b = new B(); //Compile error 
    } 
} 

Другими словами, вы должны либо добавить конструктор без параметров в классе IPanel (или добавить вызов супер конструктор с соответствующими аргументами), но я считаю, что это не то, что вы хотите сделать здесь ,

Теперь, что касается других вопросов, это может быть связано с несколькими причинами, и это всегда будет предположение без полного кода. Также подумайте, что когда вы собираетесь расширить класс IPanel с помощью некоторого класса Panel, если вы хотите переопределить метод paintComponent на этой панели и по-прежнему рисовать фон, вы должны позвонить super.paintComponent(g);, попробуйте выяснить, , почему.