继承的含义
面向对象编程,最重要的就是类的设计。如何将一类事务抽象成所需要的类是我们最常考虑的,继承是面向对象设计的第二大特性,通过继承,我们可以将原来的类进行了复用和扩充了特性,而类的继承机制,就大大增加了代码的可重用性和可扩充性。
在java中,大家一定要记住,java只支持单继承机制,即一个类只能最多继承于另一类,也就是说,一个子类最多只能有一个父类,这里就很好理解了,一个孩子的父亲只能有一个对吧O(∩_∩)O。
实现继承的格式
class 子类名 extends 父类;
下面我给大家写两个例子,让大家明白继承的好处,即演示一下代码的重用性和可扩充性问题
例如:有一个类Person,我们作为父类,有姓名和年龄这两个属性,还有说话的行为。这时候有一个学生类,他有三个属性姓名,年龄,学校,还有说话和学习的行为。当没有继承的时候,我们来写一下
代码演示:
package demo; import com.sun.media.jfxmedia.control.VideoDataBuffer; import com.sun.org.apache.bcel.internal.generic.NEW; class People{ private String name; private int age; public People(String name, int age) { this.name = name; this.age = age; } public void talk(){ System.out.println("我的名字叫"+this.name+",我的年龄是"+this.age); } } class Student{ private String name; private int age; private String school; public Student(String name, int age,String school) { this.name = name; this.age = age; this.school = school; } public void talk(){ System.out.println("我的名字叫"+this.name+",我的年龄是"+this.age); } public void study(){ System.out.println("我在"+this.school+"学校读书"); } } public class InheritDemo { public static void main(String[] args){ Student stu = new Student("bigdodo", 20, "北大"); stu.talk(); stu.study(); } }
代码讲解:这里并没有用上继承,而是创建了两个类,然后只用上了我们需要的学生类,下面给大家演示一下继承机制
代码演示:
package demo; class People{ private String name; private int age; public People(String name, int age) { this.name = name; this.age = age; } public void talk(){ System.out.println("我的名字叫"+this.name+",我的年龄是"+this.age); } } class Student extends People{ private String name; private int age; private String school; public Student(String name, int age,String school) { super(name, age); this.school = school; } public void study(){ System.out.println("我在"+this.school+"学校读书"); } } public class InheritDemo { public static void main(String[] args){ Student stu = new Student("bigdodo", 20, "北大"); stu.talk(); stu.study(); } }
代码讲解:这里我们并没有对父类People做出修改和操作,我们对Student类修改了三个地方,第一个地方,在类名边上我们用extends,声明了我们继承了People类,也就告诉了java我们的Student是People的子类,第二个地方,修改了Student类的构造方法,我们加入了super关键字,将其中两个参数传给父类的构造器了。这里大家先记得是这样使用的,我们下面接着来讲为什么。最后修改的一个地方是,我们将子类的talk()方法拿掉了,但是在使用的时候发现,我们还是可以用stu.talk(),调用这个方法,这里其实是我们调用了父类的talk()方法,我们将它继承过来了,所以不需要自己写,直接调用父类的方法即可。
继承的限制
限制1
java可以单继承,不能够多重继承,但是可以多层继承
限制2
从父类继承的私有成员,不能被子类直接使用
子类在继承父类的时候会将父类的全部成员(包括属性和方法)继承下来,但是对所有的非私有(private)成员属于显示继承,而对于所有的私有成员采用隐式继承,即子类是不可见的,子类无法直接操作访问这些属性,必须通过getter和setter方法来间接的操作
限制3
子类在进行对象的实例化时候,从父类继承而来的数据成员(属性),需要先调用父类的构造方法来初始化,然后再用子类的构造方法来初始化本地数据成员。
限制4
final关键字修饰的类不可以被继承,final有最终的,终结的意思,大家只需要记住即可。
根据限制3,我们来做一个简单的测试
代码演示:
package demo; class People{ public People(){ System.out.println("调用了父类的构造方法"); } } class Student extends People{ public Student() { System.out.println("调用了子类的构造方法"); } } public class ConstructorDemo { public static void main(String[] args) { Student student = new Student(); } }
代码结果:
super关键字
通过上面的例子,我们可以得到初步结论,super关键字的主要功能是完成子类调用父类中的属性或方法,调用super(),必须卸载子类构造方法的第一行,否则编译不通过,会出现报错。实际上,通过上面的例子,可以知道,子类构造方法第一条语句,都是隐式的调用了super()。super关键字除了调用父类的构造方法,还可以调用父类的属性和方法
调用父类的属性:super.属性名;
调用父类的方法: super.方法名();
方法的重写(覆写)
回到第二代码演示,我们记得,在继承的时候,因为父类有了talk()方法,所以我们在子类Student类中并没有写出talk()方法,但是如果这个学生是外国人怎么办?其实在java中给我们提供了方法重写的功能
代码演示:
package demo; class People{ private String name; private int age; public People(String name, int age) { this.name = name; this.age = age; } public void talk(){ System.out.println("我的名字叫"+this.name+",我的年龄是"+this.age); } } class Student extends People{ private String name; private int age; private String school; public Student(String name, int age,String school) { super(name, age); this.school = school; } public void talk(){ System.out.println("my name is "+this.name+" and i'm "+this.age+"years old"); } public void study(){ System.out.println("我在"+this.school+"学校读书"); } } public class InheritDemo { public static void main(String[] args){ Student stu = new Student("bigdodo", 20, "北大"); stu.talk(); stu.study(); } }
代码结果:
代码讲解:我们发现,这时候我们的name值和age值都没法取到,为什么呢?
原因是这样的,我们将name和age属性是通过super()关键字调用的父类的构造方法的,那这两个私有的属性在子类是不可见的,这里大家应该想起来了吧,父类的私有属性,在子类是隐式不可见的,需要通过getter方法和setter方法才能取到,这时候我们修改代码如下
代码演示:
package demo; class People{ private String name; private int age; public People(String name, int age) { this.name = name; this.age = age; } public void talk(){ System.out.println("我的名字叫"+this.name+",我的年龄是"+this.age); } public String getName() { return name; } public int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } } class Student extends People{ private String name; private int age; private String school; public Student(String name, int age,String school) { super(name, age); this.school = school; } public void talk(){ System.out.println("my name is "+super.getName()+" and i'm "+super.getAge()+"years old"); } public void study(){ System.out.println("我在"+this.school+"学校读书"); } } public class InheritDemo { public static void main(String[] args){ Student stu = new Student("bigdodo", 20, "北大"); stu.talk(); stu.study(); } }
代码讲解:在这我们在父类方法里面写上了getter()和setter()方法,这时候子类的talk()方法里我们就可以通过super关键字调用父类的getter()方法,来获取到父类私有属性里的值了
总结点评:java的面向对象第二大特性——继承,虽然内容有点多,但其实很实用,并且你会一直用到,所以本章节读者们应该仔细阅读,并多敲敲代码,发现问题,这时候的每次发现问题都不可怕,能发现问题都是进步,可以自己尝试解决,解决不了,也欢迎大家评论留言bigdodo会给大家耐心解答。感谢你的阅读!