面试官:来,翻译翻译,什么是继承~
继承
1. 什么是继承
继承是面向对象三大特征之一。
从字面意思理解就是“通过继承一个人的财产,从一无所有变得无所不有。”
这让我想起了电影《西虹市首富》,处于人生低谷期的王多鱼偶然间继承了二爷遗产,从此走向人生巅峰。
面向对象的继承其实来源于现实生活,子类通过继承父类,获取父类的属性和方法。
2. 为什么要用继承
先看一下下面的例子:
- 新建一个学生类
public class Student {
// 姓名
private String name;
// 年龄
private int age;
// 性别 0-女 1-男
private int sex;
public Student() {
}
public Student(String name, int age, int sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void eat(){
System.out.println("学生要吃饭");
}
public void study(){
System.out.println("学生要学习");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
}
复制代码
- 新建一个教师类
public class Teacher {
// 姓名
private String name;
// 年龄
private int age;
// 性别 0-女 1-男
private int sex;
public Teacher() {
}
public Teacher(String name, int age, int sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void eat(){
System.out.println("老师要吃饭");
}
public void teach(){
System.out.println("老师要讲课");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
}
复制代码
我们发现教师类和学生类都有姓名、年龄、性别的特征,也都需要吃饭。两个类都写一遍相同的属性和方法是不是“脱裤子放屁,多此一举?”
如果几千个类都有这些相同的特征,哪怕是复制粘贴是不是也累死人?
那可不可以把这些相同的特征都放在同一个类中,让其他类继承它?就相当于也拥有了这些特征?
答案是可以的。
3. 继承的使用
3.1 语法格式
继承关键字:extends
class 类名 extends 父类名{
方法+属性
}
复制代码
3.2 使用继承
- 新建一个 Person 类,将学生类和教师类的相同特征都放里面。
public class Person {
// 姓名
private String name;
// 年龄
private int age;
// 性别 0-女 1-男
private int sex;
public Person() {
}
public Person(String name, int age, int sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void eat(){
System.out.println("人要吃饭");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
}
复制代码
- 新建一个学生类继承 Person 类
public class Student extends Person{
private void study(){
System.out.println("学生要学习");
}
}
复制代码
- 新建一个教师类继承 Person 类
public class Teacher extends Person {
private void teach(){
System.out.println("老师要讲课");
}
}
复制代码
测试:
// 继承测试类
public class ExtendTest {
public static void main(String[] args) {
Student student = new Student();
student.setName("一颗雷布斯");
student.setAge(19);
Teacher teacher = new Teacher();
teacher.setName("张三丰");
teacher.setAge(30);
System.out.println("学生姓名:"+student.getName());
System.out.println("学生年龄:"+student.getAge());
student.eat();
System.out.println("---------------------------");
System.out.println("老师姓名:"+teacher.getName());
System.out.println("老师年龄:"+teacher.getAge());
teacher.eat();
}
}
复制代码
运行结果:
3.3 继承的特点
-
- java 中的继承只支持单继承,不支持多继承。不能写成 class E extends A,B,C,D{ }。
-
- B 类继承 A 类,A 类叫做父类、超类,B 类叫做子类、派生类。
-
- 子类继承父类,除了父类的构造方法和 private 修饰的数据不能被继承外,其他的都可以被继承。
-
- C 类继承 B 类,B 类继承 A 类,C 类其实相当于间接继承了 A 类。想象一下孙子和爷爷的关系。
-
- java 中所有类默认继承 Object 类,Object 类是所有类的根类(老祖宗)。
3.4 继承使用的场景
你创建了很多类,这些类有很多相同的属性或者方法,可以用继承。
4. 方法重写与重载
上面的例子中,学生类和教师类都继承了 Person 类,都拥有了eat( )方法,两者方法的输出结果都是“人要吃饭”。
但是老师类想要的是“老师吃饭”,学生类想要的是“学生吃饭”,有没有解决办法?
有的,方法重写。
4.1 方法重写
方法重写 (Override) 是子类对继承的父类的方法进行重新修改, 返回值和形参都不能改变,只是方法体变了。
-
- 两个类有继承关系
-
- 具有相同方法名、形参列表、返回值类型
例如:
public class Student extends Person{
public void eat(){
System.out.println("学生要想学习好,必须好好吃饭!!");
}
}
复制代码
// 继承测试类
public class ExtendTest {
public static void main(String[] args) {
Student student = new Student();
student.eat();
}
}
复制代码
运行结果:
4.2 方法重载
说了方法重写,不得不提一下方法重载。
方法重载 (overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
在同一个类当中,如果功能相似,可以使用重载。
例如:
public class Student extends Person{
public void eat(){
System.out.println("学生要想学习好,必须好好吃饭!!");
}
public void eat(String name){
System.out.println(name+"在吃饭");
}
public void eat(int age,String name){
if(age > 18){
System.out.println(name+"喜欢吃牛肉");
}else {
System.out.println(name+"喜欢吃猪肉");
}
}
}
复制代码
// 继承测试类
public class ExtendTest {
public static void main(String[] args) {
Student student = new Student();
student.eat();
student.eat("波吉");
student.eat(14,"卡克");
}
}
复制代码
运行结果:
上面的 eat() 方法其实就用到了方法重载。
5. super 关键字
super 字面意思是“超级的”,那必定是跟超类(父类)相关。
讲 super 之前,我们先来回忆一下 this 关键字。
-
- this 是一个关键字,是一个引用,保存了当前对象的内存地址。
-
- this 出现在实例方法中代表的是当前对象。
-
- this 不能使用在静态方法中。
-
- 当用来区分局部变量和实例变量时,this 不能省略。
-
- this 既可以出现在构造方法中,也可以出现在实例方法中。
与 this 相比,super 代表父类的引用,用于访问父类的属性、方法和构造器。
- 1 创建子类对象,默认会先调用父类的构造方法,因为先有父,再有子。例如:
public class A {
public A() {
System.out.println("父类构造方法被调用了");
}
}
复制代码
public class B extends A{
public B() {
System.out.println("子类构造方法被调用了");
}
}
复制代码
public class ExtendTest {
public static void main(String[] args) {
B b = new B();
}
}
复制代码
运行结果:
-
- 使用 super. 属性 和 super.方法名() 访问父类的属性和方法,例如:
public class A {
public String name = "哈哈哈";
public void eat(){
System.out.println("父亲要吃饭");
}
}
复制代码
public class B extends A{
private String name = "哦哦哦";
public void print(){
System.out.println("父亲名字:"+super.name);
System.out.println("儿子名字:"+this.name);
}
public void eat() {
System.out.println("儿子要吃饭");
super.eat();
}
}
复制代码
public class ExtendTest {
public static void main(String[] args) {
B b = new B();
b.print();
b.eat();
}
}
复制代码
运行结果:
-
- super不能使用在静态方法中。
-
- 父类和子类中有同名属、方法,子类想访问父类,super. 不能省略
6. Object 类
上面我们提到 Object 类是所有类的祖宗,所有的类默认都继承 Object 类。既然继承了它,那肯定是得到了他的一些属性和方法。
例如:
public class ExtendTest {
public static void main(String[] args) {
Student student = new Student();
student.setName("波吉");
student.setAge(14);
System.out.println(student.toString());
System.out.println(student.getName().equals("卡克"));
}
}
复制代码
运行结果:
6.1 toString()
toString() 该方法在打印对象时被调用,将对象信息变为字符串返回,默认输出对象地址。
上面的例子中输出的是一串内存地址,我们不知道什么意思,可以通过重写 Object 类的 toString() 方法来输出对象属性信息。
例如:
public class Student extends Person{
@Override
public String toString() {
return "姓名:"+this.getName()+",年龄:"+this.getAge();
}
}
复制代码
public class ExtendTest {
public static void main(String[] args) {
Student student = new Student();
student.setName("波吉");
student.setAge(14);
System.out.println(student.toString());
}
}
复制代码
运行结果:
6.2 equals()
该方法用于比较对象是否相等,例如:
public static void main(String[] args) {
String name1= "波吉";
String name2= "波吉";
System.out.println(name1.equals(name2));
}
复制代码
运行结果: