关键字super
程序员文章站
2022-03-02 14:35:01
...
关键字super明确显式地指出一个类可以它父类的构造函数、方法和变量。
关键字super和继承一起建立类和它的父类的紧密联系。继承隐含地指出子类对父类所拥有的访问权限。例如,当我们要调用一个实例方法时,如果实例本身并没有定义该方法,那我们自然地会得到它的父类中定义的同名方法。尽管会因为方法的覆盖或者使用定义与父类一样的实例或类变量(叫做“隐藏”)而失去这种访问的权力。这就是为什么要使用super这个关键字,它显式地指出子类可以直接访问父类中的某些部分,尽管有时这种访问会因为种种原因被屏蔽了的方法在其父类中的原始代码。
关键字Super在构造函数的使用中是非常重要的,和方法不同,构造函数是不能继承的;因此super是访问父类中构造函数的惟一途径。在子类的构造函数中,使用super(...)和适当的参数表可以触发对父类构造函数的一个条用,如果父类没有相应的构造函数,编译器会报错,这就是每个实例实现的初始化的过程链。实例先把自己作为一个Object实例进行初始化,然后从它的直接子类开始按照继承链依次调用构造函数直到最后将与当前类直接相关的内容初始化完毕。
例如,下面的Frame子类定义了两个构造函数,以便与Frame类提供的两个构造函数相匹配:
在这个例子中,
http://www.kpwang.com/尽管两个构造函数只有简单地调用了父类的构造函数,而没有其他什么特别之处,但是我们在使用的时候仍然要将这些语句包括进去,因为构造函数是不能自动继承的。此外,如果构造函数要调用父类的构造函数,相应的调用语句必须是新构造函数的第一条语句。
这种链式的初始化过程Java中是非常重要的,以至于如果在程序中没有给出这种调用语句,系统便会自动地将它包括进去。系统自动调用的构造函数总是不带任何参数的那一个。例如JDk中Button类包含以下构造函数代码:
系统自动调用的缺省构造函数是没有任何参数的,但是可以显式地去调用父类中任一个带参数的构造函数。
Super的第二个常见用法是一个方法中去访问父类中的同名方法,这在含有方法覆盖的方法定义中显得非常有意义。在上下文中,super允许您定义一个覆盖函数:它可以通过调用父类中的方法而不是简单地用新代码完全替换掉它的方式覆盖。AWT的Button类再一次提供了一个简单例子:
因为Button是Component的子类,它的paramString()方法会去调用Component的paramString方法,它返回一个 String类的字符串实例来描述和所有组件有关的参数,然后将按钮的标签添加到字符串中。因此,每个按钮如果调用paramString()方法就会返回一个包括按钮尺寸,在屏幕上的位置(所有AWT组件都有的信息)和按钮标签值(特定按钮子类的信息)等信息的字符串实例。
最后,我们还可以用super去访问被子类中同名变量隐藏的父类中变量。下列代码片段就给了一个简单示例:
关键字super和继承一起建立类和它的父类的紧密联系。继承隐含地指出子类对父类所拥有的访问权限。例如,当我们要调用一个实例方法时,如果实例本身并没有定义该方法,那我们自然地会得到它的父类中定义的同名方法。尽管会因为方法的覆盖或者使用定义与父类一样的实例或类变量(叫做“隐藏”)而失去这种访问的权力。这就是为什么要使用super这个关键字,它显式地指出子类可以直接访问父类中的某些部分,尽管有时这种访问会因为种种原因被屏蔽了的方法在其父类中的原始代码。
关键字Super在构造函数的使用中是非常重要的,和方法不同,构造函数是不能继承的;因此super是访问父类中构造函数的惟一途径。在子类的构造函数中,使用super(...)和适当的参数表可以触发对父类构造函数的一个条用,如果父类没有相应的构造函数,编译器会报错,这就是每个实例实现的初始化的过程链。实例先把自己作为一个Object实例进行初始化,然后从它的直接子类开始按照继承链依次调用构造函数直到最后将与当前类直接相关的内容初始化完毕。
例如,下面的Frame子类定义了两个构造函数,以便与Frame类提供的两个构造函数相匹配:
class exapleframe extends Frame(){
public ExampleFrame(){
super();
}
public ExampleFrame(String title_kpwang_com){
super(title_kpwang_com);
}
//... field and method definitions
}
在这个例子中,
http://www.kpwang.com/尽管两个构造函数只有简单地调用了父类的构造函数,而没有其他什么特别之处,但是我们在使用的时候仍然要将这些语句包括进去,因为构造函数是不能自动继承的。此外,如果构造函数要调用父类的构造函数,相应的调用语句必须是新构造函数的第一条语句。
这种链式的初始化过程Java中是非常重要的,以至于如果在程序中没有给出这种调用语句,系统便会自动地将它包括进去。系统自动调用的构造函数总是不带任何参数的那一个。例如JDk中Button类包含以下构造函数代码:
/* in Button.java(JDK 1.0.2) */
public Button(String label_kpwang_com){
this.label_kpwang_com = label_kpwang_com;
}
因为父类的构造函数会被自动包括进去,所有上面的代码就等于:
/* Equivalent Button constructor: */
public Button(String label_kpwang_com){
super();
this.label_kpwang_com = label_kpwang_com;
}
系统自动调用的缺省构造函数是没有任何参数的,但是可以显式地去调用父类中任一个带参数的构造函数。
Super的第二个常见用法是一个方法中去访问父类中的同名方法,这在含有方法覆盖的方法定义中显得非常有意义。在上下文中,super允许您定义一个覆盖函数:它可以通过调用父类中的方法而不是简单地用新代码完全替换掉它的方式覆盖。AWT的Button类再一次提供了一个简单例子:
/* in Button.java(JDK 1.0.2) */
Protected String paramString(){
return super.paramString()+",label_kpwang_com="+label_kpwang_com;
}
因为Button是Component的子类,它的paramString()方法会去调用Component的paramString方法,它返回一个 String类的字符串实例来描述和所有组件有关的参数,然后将按钮的标签添加到字符串中。因此,每个按钮如果调用paramString()方法就会返回一个包括按钮尺寸,在屏幕上的位置(所有AWT组件都有的信息)和按钮标签值(特定按钮子类的信息)等信息的字符串实例。
最后,我们还可以用super去访问被子类中同名变量隐藏的父类中变量。下列代码片段就给了一个简单示例:
class X{
int foo = l;//declaree instance variable foo
}
class SubX{
int foo = 2;//declaree own version of foo, which hides the
//superclass version
int getSuperFoo(){
return super.foo;//return l,not 2
}
}