Here I found this code:
import java.awt.*;
import javax.swing.*;
public class FunWithPanels extends JFrame {
public static void main(String[] args) {
FunWithPanels frame = new FunWithPanels();
frame.doSomething();
}
void doSomething() {
Container c = getContentPane();
JPanel p1 = new JPanel();
p1.setLayout(new BorderLayout());
p1.add(new JButton("A"), BorderLayout.NORTH);
p1.add(new JButton("B"), BorderLayout.WEST);
JPanel p2 = new JPanel();
p2.setLayout(new GridLayout(3, 2));
p2.add(new JButton("F"));
p2.add(new JButton("G"));
p2.add(new JButton("H"));
p2.add(new JButton("I"));
p2.add(new JButton("J"));
p2.add(new JButton("K"));
JPanel p3 = new JPanel();
p3.setLayout(new BoxLayout(p3, BoxLayout.Y_AXIS));
p3.add(new JButton("L"));
p3.add(new JButton("M"));
p3.add(new JButton("N"));
p3.add(new JButton("O"));
p3.add(new JButton("P"));
c.setLayout(new BorderLayout());
c.add(p1, BorderLayout.CENTER);
c.add(p2, BorderLayout.SOUTH);
c.add(p3, BorderLayout.EAST);
pack();
setVisible(true);
}
}
I do not understand how "doSomething" use the fact that "frame" is an instance of the class JFrame. It is not clear to me because there is no reference to "this" in the code for the method "doSomething".
ADDED:
Maybe this is related. In this code:
import java.awt.*;
import java.applet.Applet;
public class ButtonGrid extends Applet {
public void init() {
setLayout(new GridLay开发者_Go百科out(3,2));
add(new Button("1"));
add(new Button("2"));
add(new Button("3"));
add(new Button("4"));
add(new Button("5"));
add(new Button("6"));
}
}
In the "init" method we use methods "setLayout" and "add" and we do not bind them to a particular object (for example objectName.setLayout(...)
). Why is that?
While this
is not used, the method makes frequent use of JFrame methods, notably in the first line of the method where it gets the content pane Container c = getContentPane();
Using the this
keyword would make the example clearer, but you don't need it.
The example could be rewritten as:
import java.awt.*;
import javax.swing.*;
public class FunWithPanels extends JFrame {
public static void main(String[] args) {
FunWithPanels frame = new FunWithPanels();
frame.doSomething();
}
void doSomething() {
Container c = this.getContentPane();
// .. snip unaltered code
this.pack();
this.setVisible(true);
}
}
This is fully equivalent.
This because this
is implicit in the search path of the compiler. The compiler will look for a variable in this order:
- A local variable in the current block
- A local variable in an outer block
- A method parameter
- A field in the current class (i.e. relative to
this
) - A field in a parent class
There's an implicit usage of this
in this line:
Container c = getContentPane();
getContentPane()
is equivalent to this.getContentPane()
here.
I do not understand how "doSomething" use the fact that "frame" is an instance of the class JFrame
because FunWithPanels extends JFrame
, and every method you define in FunWithPanels will be called on an instance of FunWithPanels.
If I am not misunderstanding something, the answer is trivial:
The compiler does not need the this.
qualifier to detect when a member of the class is being used. The only need to explicitly use this.
is when there is a name clash, like in
public MyClass {
private Foo foo;
MyClass(Foo foo) {
this.foo = foo;
}
}
Update: Apparently I did indeed misunderstand the question... although I am apparently not alone with it.
Anyway, doSomething()
calls getContentPane()
, which is a method of JFrame
, and pack()
and setVisible()
from the JFrame
parent class, Window
. However, that in itself would not make it necessary for FunWithPanels
to extend JFrame
, since all these methods are public, accessible to anyone.
I believe the author thought that FunWithPanels
is a specialized type of JFrame
, this is why it became a subclass. This way FunWithPanels
can be used anywhere where a generic JFrame
is required. See the Liskov Substitution Principle for more explanation. (Note: this may or may not be good class design, but I can't say much about it without knowing the context).
精彩评论