🎉一. 继承的概念
1.1 为什么需要继承
生活中的继承:
兔子和羊属于食草动物类,狮子和豹属于食肉动物类。
食草动物和食肉动物又是属于动物类。
所以继承需要符合的关系是:is-a,父类更通用,子类更具体。
虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。
为了方便大家理解,我们举个例子,我们定义一个猫和够,他们都有自己的名字和年龄,这是他们所共有的,但是他们表现出不同的行为,比如狗会汪汪叫,猫会喵喵叫,我们就可以把他们共有的特性抽取出去,写成一个父类,看代码:
既然大家有着同样的属性和方法,我们就可以这样改写:
么,这里继承的概念就出来了,没错,这就是继承!从这里不难看出,继承实际上就是用来对共性的抽取,实现对代码的复用!
1.2 继承的概念
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类,继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
继承的格式:
在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:
class父类 { } class子类extends父类 { }
1.3继承的语法
语法1.2中就给大家介绍完了,我们这里看一下具体的实现吧,代码:
classAnimal { publicStringname; publicintage; publicvoidageShow() { System.out.println(name+"今年"+age+"岁了"); } } classDogextendsAnimal { publicvoidwangwang() { System.out.println(name+"汪汪叫!"); } } classCatextendsAnimal { publicvoidmiaomiao() { System.out.println(name+"喵喵叫!"); } } publicclassTest_2 { publicstaticvoidmain(String[] args) { Dogdog=newDog();// dog类中并没有定义任何成员变量,name和agedog.name="旺财"; dog.age=3; dog.ageShow(); Catcat=newCat(); cat.name="咪咪"; cat.age=5; cat.ageShow(); } }
运行结果:
注意:
1. 子类会将父类中的成员变量或者成员方法继承到子类中了
2. 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
1.4 父类成员的访问
1.4.1 子类中访问父类的成员变量
1)子类和父类不存在同名成员变量
classDemo { publicinta=1; publicintb=2; publicintc=3; } classBaseextendsDemo { publicvoidfunc() { System.out.println(a); System.out.println(b); System.out.println(c); } } publicclassTest_3 { publicstaticvoidmain(String[] args) { Basebase=newBase(); base.func(); } }
2)子类和父类成员变量同名
classDemo { publicinta=1; publicintb=2; publicintc=3; } classBaseextendsDemo { inta=10; intb=20; publicvoidfunc() { System.out.println(a); System.out.println(b); System.out.println(c); } } publicclassTest_3 { publicstaticvoidmain(String[] args) { Basebase=newBase(); base.func(); } }
从上面俩个例子我们可以得出:
如果访问的成员变量子类中有,优先访问自己的成员变量。
如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
1.4.2 子类中访问父类的成员方法
1)当子类和父类中成员方法名字不同
classDemo { publicvoidBasefun1() { System.out.println("父类"); } } classBaseextendsDemo { publicvoidBasefun() { System.out.println("子类"); } publicvoidfunc() { Basefun(); Basefun1(); } } publicclassTest_3 { publicstaticvoidmain(String[] args) { Basebase=newBase(); base.func(); } }
这里也不难看出,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。
2)当子类和父类中成员方法名字相同
classDemo { publicvoidBasefun() { System.out.println("父类"); } } classBaseextendsDemo { publicvoidBasefun() { System.out.println("子类");//优先调用子类自己的方法 } publicvoidfunc() { Basefun(); } } publicclassTest_3 { publicstaticvoidmain(String[] args) { Basebase=newBase(); base.func(); } }
从输出结果我们可以出,通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
1.5 子类构造方法
子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。我们也可通过构造方法给父类中的成员变量赋值:
classAnimal { publicStringname; publicintage; publicAnimal(Stringname, intage) { //构造方法this.name=name; this.age=age; } publicvoidageShow() { System.out.println(name+"今年"+age+"岁了"); } } classDogextendsAnimal { publicvoidwangwang() { System.out.println(name+"汪汪叫!"); } publicDog(Stringname,intage){ super(name, age); } } classCatextendsAnimal { publicvoidmiaomiao() { System.out.println(name+"喵喵叫!"); } publicCat(Stringname,intage){ super(name, age); } } publicclassTest_2 { publicstaticvoidmain(String[] args) { Dogdog=newDog("旺财",3); dog.ageShow(); dog.wangwang(); Catcat=newCat("咪咪",5); cat.ageShow(); cat.miaomiao(); } }
注意:
1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法
2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
3. 在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句。
4. super(...)只能在子类构造方法中出现一次,并且不能和this同时出现
🎉二. 继承的关键字
2.1 super和this关键字
1)super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
2)this关键字:指向自己的引用。
举个例子,这里我们主要介绍super:
classTest1 { publicinta=1; publicintb=2; } classTest2extendsTest1 { publicinta=10; publicintb=20; voidfun() { System.out.println(a); System.out.println(super.b); } } publicclassTest_3 { publicstaticvoidmain(String[] args) { Test2test2=newTest2(); test2.fun(); }
如果这里我们要通过子类去访问父类中的成员,就需要在成员变量前面加上super关键字,这里我们就可以访问到上述代码中父类b的值了!
2.2 final关键字
final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。
final 含义为 "最终的"。
使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写:
publicclassTest_4 { finalinta=10; a=20;//被final修饰的变量是被密封的,不允许修改的}
classone { } finalclasstowextendsone { } classthreeextendstow{ //被final修饰的类是不能被继承的,属于密封类}