General object orientated problem
Hello,
I have a very simple question concerning object orientated sotware developement. I wrote a piece of source code, so you'll understand what my problem is:
public class Test {
public JTextField tf = new JTextField("Test");
public Test() {
JButton but = new JButton();
but.addActionListener(new MyActionListener(this));
} // constructor Test()
} // class Test
class MyActionListener implements ActionListener
{
private Test test = null;
public MyActionListener(Test test) {
this.test = test;
} // constructor MyActionListener()
public void actionPerformed(ActionEvent e) {
test.tf.setText("Text has changed now...");
} // method actionPerformed()
} // class MyActionListener
The problem is that I want to initialize an attribute from the class 'Test' in the class 'MyActionListener' (I want to change the text of the textfield...). To do so I have to give this element to the class MyActionListener by parameter. The question is now: is it better to give a copy from the whole class Test to the class MyActionListener (...as I did in the source-code...) or should I give in general only the attributes I really need to MyActionListener ?
Regards,
Findus
P.S.: Is there anywhere a good tutorial concerning object-orientated software design and developement ?
the better way is to
implement the ActionListener interface in your test class
look like this :
class Test implements ActionListener {
Test(){...
this.addActionListener(this);
}//construtor
publci void ActionPerformed(ActionEvent e){
..
handle the event here by your self
}
}
-
Robbies
--
1.java IDE tool : JawaBeginer
2.Java Jar tool : JavaJar
http://www.pivotonic.com
--
First, use [code ] [/code] tags to make things more readable.
Second, there are a couple of ways to improve your code:
1) Have your separate ActionListener class call a method on Test instead of directly modifying internal variables (think encapsulation):
import javax.swing.*;
import java.awt.event.*;
public class Test
{
public JTextField tf = new JTextField("Test");
public Test()
{
JButton but = new JButton();
but.addActionListener(new MyActionListener(this));
}
// Note this has to be public so MyActionListener can call it
public void changeText(String s)
{
tf.setText(s);
}
}
class MyActionListener implements ActionListener
{
private Test test = null;
public MyActionListener(Test test)
{
this.test = test;
}
public void actionPerformed(ActionEvent e)
{
test.changeText("Text has changed now...");
}
}
2) Use an anonymous inner class to avoid exposing what should be internal methods of Test (increased encapsulation):
import javax.swing.*;
import java.awt.event.*;
public class Test
{
public JTextField tf = new JTextField("Test");
public Test()
{
JButton but = new JButton();
but.addActionListener(
new ActionListener() // anonymous inner class
{
public void actionPerformed(ActionEvent e)
{
changeText("Text has changed now...");
}
});
}
// Since the inner class has access to private methods,
// we can stop exposing this to the world
private void changeText(String s)
{
tf.setText(s);
}
}
3) Have Test implement ActionListener:
import javax.swing.*;
import java.awt.event.*;
public class Test implements ActionListener
{
public JTextField tf = new JTextField("Test");
public Test()
{
JButton but = new JButton();
but.addActionListener(this); // since Test is now an ActionListener
}
public void actionPerformed(ActionEvent e)
{
// Note it is good practice have only one way of manipulating
// internal data, so we have changeText(String) be responsible
// for setting the text field
changeText("Text has changed now...");
}
private void changeText(String s)
{
tf.setText(s);
}
}
Generally I prefer the 3rd option. The first exposes too much, and the second may get difficult to understand and maintain.