一、基本概念
关键字:extends
在java中,一个类(类A)继承另一个类(类B)是指类A能够直接使用类B的所有非构造方法和所有非私有属性(注意:不是不能使用是不能直接使用),并在类B原有的基础上继续进行扩充和延伸,即关键字extends的含义。通常,我们称类A与类B的关系为继承关系,继承方(类A)被称为子类,被继承方(类B)被称为父类。
二、示例
class A{
//创建一个类A
private int a=0;//私有属性无法继承
public int b=0;
public void setA(){
System.out.println("公有方法子类可继承");
}
private void setB(){
System.out.println("私有方法子类不可继承");
}
}
class B extends A{
/*创建一个类B继承类A
此时可视为方法B拥有
属性b和方法setA()。
*/
}
public class Test{
public static void main(String[] args){
B b = new B();
int a = b.a;//错误,B类无法继承私有属性,因此类中无属性a
int b = b.b;//正确
b.setA();//正确
b/setB();//错误,B类无法继承私有方法,因此类中无方法setB()
}
}
由上述代码可知,父类的公有成员子类会自动继承,而私有属性子类则无法继承。
三、使用this实现构造方法的相互调用
构造方法是指与在类中与类名相同,无返回类型的方法。一个类中可以含有多个构造方法,可以带有参数,也可以不含参数,在创建对象是自动调用。通过创建对象时传入不同类型或不同数量的值来分别调用相对应的构造方法。
class A{
private i;
private j;
public A(){
this.i = 0;
this.j = 0;
//无参构造方法,后用方法A_null表示
...
}
public A(int i){
this.i = i
this.j = 0;
//有参构造方法,后用方法A_has表示
...
}
public A(int i,int j){
this.i = i;
this.j = j;
//有参构造方法,后用方法A_have表示
...
}
}
public class Test{
int a = 0;
int b = 0;
A a1 = new A();//此时很明显,A()即上面的A_null方法,即默认构造方法
A a2 = new A(a)//此时为A(int i),即A_has方法
A a3 = new A(a,b)//此时为A(int i,int j),即A_have方法
}
上述对象a1,a2,a3创建之时,将自动调用相对应的构造方法
可以看到,每当我们需要新增一个私有属性时,也许都需要新增一个构造方法
并且在每个构造方法中都需要对该属性进行初始化或赋值
但可以注意到,每个构造方法似乎都在做相同的事(此时可以将初始化也看做赋值,则所有构造方法其实都在进行赋值操作,只是赋的值可能不同)。含有最多参数的那个构造方法其实做了以上所有构造方法做的事情,如果有办法能够使除它以外的构造方法都能够调用它,统一由它来做这件事,会省很多时间,也提高了代码的可读性。
this关键字能够实现这个操作。
在构造方法中,this关键字能够实现构造方法之间的相互调用。
于是上述代码可修改为:
class A{
private i;
private j;
public A(){
this(0,0);//此时会调用A(int i,int j)构造方法
//无参构造方法,后用方法A_null表示
...
}
public A(int i){
this(i,0);//同上
//有参构造方法,后用方法A_has表示
...
}
public A(int i,int j){
this.i = i;
this.j = j;
//有参构造方法,后用方法A_have表示
...
}
}
此时无论是带参或是不带参的构造方法,具体工作全部由A_have方法实现。
需要注意的是,在使用this关键字调用其他构造方法时,需要将它放到当前构造方法的第一句。
错误的示例:
class A{
private a=0;
public A(){
a=0;
this(0);//this语句不在第一行,错误
}
......
}
四、super关键字
我们已经知道,子类会继承父类的非私有成员,那么当子类继承了父类的A()方法,而子类在父类的基础上又有所拓展,此时当你想再通过子类对象调用A()方法时,需要你重新将父类A()方法再次在子类实现一次,否则系统不会再调用父类的A()方法。
class A{
public void test(){
int i=1;
int j=2;
}
}
class B extends A{
public void test(){//父类方法的重写
//此时我们希望在父类test()方法的基础上输出i+j,则需要重新写一遍
int i=1;
int j=1;
System.out.println(i+j);
}
}
super关键字可以在子类中调用父类的某个方法,例如该题,可以在子类中使用super.test();
来调用父类方法:
class A{
public void test(){
int i=1;
int j=2;
}
}
class B extends A{
public void test(){//父类方法的重写
super.test();
System.out.println(i+j);
}
}
或是在子类的构造方法中使用“super()”来调用父类的构造方法。
五、例题
定义父类Animals,子类Cat、Dog。其中共有成员需要name与age,并且在两个子类中分别实现
其特殊方法catch()和look(),通过主方法打印出来。
import java.util.Scanner;
class Animals{
private String name;
private int age;
public Animals(){
name=" ";
age=0;
}
public Animals(String name,int age){
this.name=name;
this.age=age;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
}
class Cat extends Animals{
public Cat(){
super();
}
public Cat(String name,int age){
super(name, age);
}
public void catchs(){
System.out.println("抓老鼠");
}
}
class Dog extends Animals{
public Dog(){
super();
}
public Dog(String name,int age){
super(name, age);
}
public void look(){
System.out.println("看门");
}
}
public class Extend_2{
public static void main(String[] args) {
Cat c=new Cat();
Dog d=new Dog();
c.setName("小猫");
d.setName("小狗");
c.setAge(1);
d.setAge(2);
System.out.println("Name is "+c.getName()+",Age is "+c.getAge());
c.catchs();
System.out.println("Name is "+d.getName()+",Age is "+d.getAge());
d.look();
}
}
运行结果:
Name is 小猫,Age is 1
抓老鼠
Name is 小狗,Age is 2
看门