因此,我正在扩展Java Rectangle类。我碰巧对this
和super
的使用以及何时应使用它们感到困惑。我知道super
是超类(父类),而this
是您从中调用它的当前类。
我目前有一个从BetterRectangle
类扩展的Rectangle
类和一个方法:
boolean isCongruent(Rectangle r)
{
if(r.width == super.width && r.height == super.height)
{
return true;
}
return false;
}
如果我使用this.width
和this.height
而不是super
是否重要?
不管两者给我相同的答案,哪种方法更正确?
答案 0 :(得分:1)
如果您的子类具有字段width
(和height
),那么根据初始化字段的方式,super.width
的值可以与this.width
不同。这是一个快速测试:-
import java.awt.*;
public class BetterRectangle extends Rectangle {
public int width;
void testWidth() {
System.out.println("width = " + width);
System.out.println("this.width = " + this.width);
System.out.println("super.width = " + super.width);
}
}
-
public static void main(String[] args) {
Rectangle rect = new BetterRectangle();
rect.width = 10; //sets the value of super class's field
((BetterRectangle) rect).width = 90; //sets the value of subclass's field
((BetterRectangle) rect).testWidth();
}
此打印:-
width = 90
this.width = 90
super.width = 10
请注意,由于数据隐藏,width
和this.width
会打印相同的内容。您必须添加super关键字才能访问超类的字段。
如果子类中没有width
变量,那么super.width
和this.width
指向同一个字段,那么为什么不只使用width
? / p>
希望这会有所帮助。
答案 1 :(得分:1)
通常,几乎不需要真正使用这两种方法。或超级。
看看您的iscongruent()方法,问问自己它怎么可能返回false。答案:只有当超类和子类都具有相同名称的成员时才有可能,也就是说,有多个名为“ width”和/或“ height”的distinc字段。这是不好的做法。
为什么会这样?假设这些字段具有相同的语义。在任何时候。那么,为什么该领域有两种不同的表象?这是简单的冗余,并且是错误的来源。消除两者之一,就可以解决问题。相反地,假设这些字段可能带有不同的语义。您可能希望至少通过getter(也许还有setter)在子类中公开那些语义。因此,现在您的上级和子类中都具有具有 相同 签名但具有 差异 的吸气剂(甚至是二传手)语义。那是简单的反合同设计。子类绝不能改变其父类建立的方法的语义。最后,如果您不想在子类中公开同名字段,则没有什么可以阻止您将其命名为'localWidth'或'subWidth'或任何其他由 提供的名称更好,更详细地解释了预期的语义 。
也就是说,在某些情况下,使用“ this”和/或“ super”是必要的,甚至是不可避免的:
在构造函数中,当从已与字段具有相同名称的参数值设置字段时:
this.x = x; /* x = x would mean an assignment to the method parameter, not the field */
在替代实现中,当您还需要执行超类中定义的代码时:
method ( ... ) {
super.method( ... );
/* some extra code here to deal with the extra state in the sub class */
}
可能还有更多,但总的来说,广泛使用“ this”和“ super”会导致过多的“噪音”,因此可以避免在不影响可读性的情况下避免使用 。当然,这只是见解和偏爱的样式。
答案 2 :(得分:0)
如果我使用this.width和this.height而不是super会不会很重要?
如果您的子类继承自其父类的属性(在本例中为Rectangle的width
和height
),则您的子类现在拥有width
和height
作为其子类自己的属性。
因此,如果您打算访问子类的属性,则使用this
(指的是类本身)会更有意义吗?因此,我将继续使用this
。
继承给子级的属性:
class Parent{
protected int width = 5;
protected int height = 5;
}
class Child extends Parent{
public Child(int width, int height){
this.width = width;
this.height = height;
}
public int getHeight() {
return this.height;
}
public int getWidth() {
return this.width;
}
public int getSuperHeight() {
return super.height;
}
public int getSuperWidth() {
return super.width;
}
}
测试运行:
Child c = new Child(2, 3);
System.out.println(c.getWidth() + " " + c.getHeight()); //2 3
System.out.println(c.getSuperWidth() + " " + c.getSuperHeight()); //2 3
就像ScarryWombat提到的那样,如果属性被子类中声明的属性掩盖,则使用this
和super
会有所不同。 this
现在引用子类中声明的属性,而不是继承的属性。
继承给子级但被屏蔽的属性:
class Child extends Parent{
private int width;
private int height;
public Child(int width, int height){
this.width = width;
this.height = height;
}
public int getHeight() {
return this.height;
}
public int getWidth() {
return this.width;
}
public int getSuperHeight() {
return super.height;
}
public int getSuperWidth() {
return super.width;
}
}
测试运行:
Child c = new Child(2, 3);
System.out.println(c.getWidth() + " " + c.getHeight()); //2 3
System.out.println(c.getSuperWidth() + " " + c.getSuperHeight()); //5 5
答案 3 :(得分:-1)
最好的方法可能是查看标准Java类如何访问变量。 javax.swing.text.DefaultCaret
扩展了Rectangle
。除非存在局部变量冲突-否则变量访问不使用任何this
或super
指定符。我会坚持:)。
例如,这是repaint
方法:
protected final synchronized void repaint() {
if (component != null) {
component.repaint(x, y, width, height);
}
}