概述
本文深入探讨面向对象编程的核心概念,包括继承、方法重写、this
和super
关键字的使用,以及抽象类和方法的定义与实现。通过本文的学习,你将能够:
- 理解继承的优势。
- 掌握继承的使用方法。
- 了解继承后成员变量和成员方法的访问特点。
- 掌握方法重写及其应用场景。
- 学会使用
this
关键字调用当前对象的成员。 - 学会使用
super
关键字调用父类的成员。 - 定义抽象方法和抽象类。
- 重写抽象方法。
第一章:继承
1. 什么是继承
继承是一种代码复用机制,通过将共通代码抽取到父类中,子类可以直接继承父类的功能。在Java中,使用extends
关键字实现继承。
注意点:
- 子类可以继承父类的非私有成员,但不能访问私有成员。
- 构造方法不能被继承。
学习继承:
- 应从能否“使用”的角度来学习继承,而非“拥有”。
2. 继承如何使用
定义一个父类,将重复代码放入其中。然后,定义子类继承父类,通过extends
关键字。创建子类对象后,可以直接使用父类中的非私有成员。
public class Employee {String name;int age;public void work(){System.out.println("工作");}private void eat(){System.out.println("员工要干饭");}
}public class Teacher extends Employee{}public class Manager extends Employee{
}
3. 继承中,成员变量和成员方法的访问特点
成员变量
- 不重名情况: 子类和父类可以拥有同名成员变量,但访问时会根据对象类型决定访问哪个变量。
public class Fu {int numFu = 100;
}public class Zi extends Fu{int numZi = 10;
}public class Test01 {public static void main(String[] args) {Fu fu = new Fu();System.out.println(fu.numFu);//父类中的numFuZi zi = new Zi();System.out.println(zi.numZi);System.out.println(zi.numFu);//继承了父类,可以使用父类中非私有成员}
}
- 重名情况: 当子类和父类成员变量重名时,访问时会优先使用子类的成员变量,如果子类没有,则访问父类的成员变量。
public class Fu {int numFu = 100;int num = 10000;
}public class Zi extends Fu{int numZi = 10;int num = 1000;
}
成员方法
- 方法调用: 看
new
的对象是谁,优先调用谁的方法。如果子类没有该方法,则会寻找父类中的方法。
public class Fu {public void methodFu(){System.out.println("我是父类中的methodFu");}public void method(){System.out.println("我是父类中的method方法");}
}public class Zi extends Fu{public void methodZi(){System.out.println("我是子类中的methodZi方法");}public void method(){System.out.println("我是子类中的method方法");}
}
4. 方法的重写
方法重写是指子类中有一个与父类方法名和参数列表相同的方法。使用@Override
注解可以检测是否为重写方法。
注意事项:
- 子类重写父类方法之后,权限必须要保证大于等于父类权限(权限指的是访问权限)
public -> protected -> 默认 -> private - 子类方法重写父类方法,方法名和参数列表要一样
- 私有方法不能被重写,构造方法不能被重写,静态方法不能被重写
- 子类重写父类方法之后,返回值类型应该是父类方法返回值类型的子类类型
public class Fu {public void methodFu(){System.out.println("我是父类中的methodFu方法");}public void method(){System.out.println("我是父类中的method方法");}void method01(){}/* public static void method02(){}*/public Fu method03(){return null;}
}
public class Zi extends Fu{public void methodZi(){System.out.println("我是子类中的methodZi方法");}@Overridepublic void method(){System.out.println("我是子类中的method方法");}@Overridepublic void method01(){}/* public static void method02(){}*/@Overridepublic Zi method03(){return null;}
}
使用场景: 功能升级改造,子类需要对父类中已经实现好的功能进行重新改造
public class Fu {public void methodFu(){System.out.println("我是父类中的methodFu方法");}public void method(){System.out.println("我是父类中的method方法");}
}public class Zi extends Fu{public void methodZi(){System.out.println("我是子类中的methodZi方法");}@Overridepublic void method(){System.out.println("我是子类中的method方法");}
}
第二章:super
和this
1. 继承中构造方法的特点
- 当创建子类对象时,会先初始化父类,即执行父类的构造方法。
public class Fu {public Fu(){System.out.println("我是父类中的无参构造");}
}public class Zi extends Fu{public Zi(){super();System.out.println("我是子类中的无参构造");}public Zi(int i){super();System.out.println("我是子类中的有参构造");}
}
2. super
和this
的具体使用
super
- 调用父类构造方法: 在子类构造方法中使用
super()
调用父类无参构造,或使用super(实参)
调用父类有参构造。 - 调用父类成员变量和方法: 使用
super.成员变量名
和super.成员方法名(实参)
。
public class Fu {int num = 10;public Fu(){System.out.println("我是父类中的无参构造");}public Fu(int data){System.out.println("我是父类中的有参构造");}public void method(){System.out.println("我是父类中的method方法");}
}public class Zi extends Fu{int num = 100;public Zi(){super();System.out.println("我是子类中的无参构造");}public Zi(int num){super(10);System.out.println("我是子类中的有参构造");}public void method(){super.method();System.out.println("我是子类中的method方法");System.out.println(num);System.out.println(super.num);}
}
this
- 调用当前对象的构造方法: 在构造方法中使用
this()
调用当前对象的无参构造,或使用this(实参)
调用当前对象的有参构造。 - 调用当前对象的成员变量和方法: 使用
this.成员变量名
和this.成员方法名(实参)
。
public class Person {int num = 10;public Person(){this();System.out.println("我是Person中的无参构造");}public Person(int data){this();System.out.println("我是Person中的有参构造");}public void method(){int num = 20;System.out.println(num);System.out.println(this.num);this.method01();System.out.println("我是Person类中的method方法");}public void method01(){System.out.println("我是Person类中的method01方法");}
}
3. 继承的特点
- Java只支持单继承,不支持多继承。
- 继承支持多层继承。
- 一个父类可以有多个子类。
- 构造方法、私有方法和静态方法不能被继承或重写。
第三章:抽象
1. 抽象的介绍
抽象类和抽象方法是面向对象编程中用来表达共性和多样性的工具。抽象方法没有具体实现,必须在子类中重写。
关键字:
abstract
用于定义抽象方法和抽象类。
注意事项:
- 抽象方法所在的类必须是抽象类。
- 子类必须重写父类中的所有抽象方法,除非子类也是抽象类。
- 抽象类不能被直接实例化,只能通过子类对象来调用重写的方法。
public abstract class Animal {public abstract void eat();public abstract void drink();
}public class Dog extends Animal{@Overridepublic void eat() {System.out.println("狗啃骨头");}@Overridepublic void drink() {System.out.println("狗喝水");}
}
2. 抽象的注意事项
- 抽象类不能直接创建对象,只能创建非抽象子类的对象。
- 抽象类中可以包含成员变量、构造方法和成员方法。
public abstract class Employee {private String name;private int age;public Employee() {}public Employee(String name, int age) {this.name = name;this.age = age;}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 abstract void work();
}
第四章:综合案例
本章节通过一个IT公司的员工体系案例,展示了如何定义类、指定继承关系,并实现工作方法的调用。
案例描述:
某IT公司根据员工的工作内容,划分了不同的部门和职位。每个员工都有员工编号和姓名,并执行他们负责的工作。
类的定义和继承关系:
Employee
:基类,包含员工编号和姓名。Developer
:抽象类,继承自Employee
,代表研发部员工。JavaEE
、Android
:具体类,继承自Developer
,代表不同的研发工程师。Maintainer
:抽象类,继承自Employee
,代表维护部员工。Network
、Hardware
:具体类,继承自Maintainer
,代表不同的维护工程师。
对象创建和方法调用:
通过创建具体工程师类的对象,调用work
方法,展示每个员工的工作内容。
public abstract class Employee {private int id;private String name;public Employee() {}public Employee(int id, String name) {this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public abstract void work();
}public abstract class Developer extends Employee{
}public class JavaEE extends Developer{@Overridepublic void work() {System.out.println("员工号为:"+this.getId()+"的"+this.getName()+"正在开发网站");}
}public class Android extends Developer{@Overridepublic void work() {System.out.println("员工号为:"+this.getId()+"的"+this.getName()+"正在开发app");}
}public class Test01 {public static void main(String[] args) {JavaEE javaEE = new JavaEE();javaEE.setId(1);javaEE.setName("涛哥");javaEE.work();System.out.println("===============");Android android = new Android();android.setId(2);android.setName("金莲");android.work();}
}