面向对象的三大特征: 继承 封装 多态
继承:
继承是面向对象的三大特性之一,是指一个类继承另一个类的属性和方法,使得子类具有父类的属性和方法。
继承的好处:
提高代码的复用性
父类的属性与方法 子类中如果也需要直接继承父类就可以不用自己再去定义
提高代码的维护性
多个子类中 都需要增加一个属性和方法 或者修改删除一个属性和方法,那么 直接在父类中操作就可以
提高代码的扩展性
一个父类要增加一个子类 创建了一个新的类继承父类就可以了
方法重写:子类中可以重写父类的方法,要求是参数必须一致
1、子类可以基于父类的方法之上增加相关自己特性的代码
2、子类可以完全重构父类的方法
子类以及子类对象优先调用重写之后的方法
继承的格式:
class 子类名 extends(扩展) 父类名{
}
例如:
class Student extends Person{}
方法重载:
同一个类中,创建多个同名的方法,每个方法的参数必须不一致,这种现象称为方法重载
参数不一致:(数量 类型 顺序)
返回值、访问权限修饰符可以不一致 也可以一致
根据你调用时 传入的参数 来决定 调用重载方法中对应参数类型的方法
多态——一个对象可以具备多种类型状态
本类状态 以及 父类类型状态
不管处于什么状态 调用重写的方法 都是调用子类的重写方法
多态的例子——不管是大学生还是小学生都可以看书
可以用学生身份看书->一致性较强
大学生/小学生实际上看的是不同的书->多种状态
A 是大学生类型
B 是学生类型(B是A的父类)
代码格式:
A a =new A();//a是一名大学生对象
B b =new B();//b时一名学生对象
packagecombk.a01ui.zyf0314;
importjava.util.Random;
public class Student{
// 公开的: 整个项目下都可以调用
public String stu_name;
//私有的: 只能在本类中使用
private int stu_age;
// 受保护的: 同一个package可以调用 不同的package的子类中可以调用
protected int id;
// 包默认: 同一个package可以调用
int score;
// 常量属性 每个对象都会有自己的一份
final int stu_id;// 直接赋值导致的问题是 每个对象的这个值都一致
// 构造方法:
// 1: 每个类都有一个隐式的空参数构造方法
// 2: 如果一个类显式的定义了构造方法(不管带不带参数),那么隐式的构造方法就会被覆盖
// 3: 每个类可以基于 方法重载 创建多个构造方法
// 4: 构造方法的名称必须和类名一致,没有返回值结构
// 5: 构造方法是创建对象时调用 new 类构造方法(构造方法带的参数);
// 6: 构造方法与构造代码块同属于 初始化空间可以给常量初始赋值(每个构造方法中都要有赋值
的代码)
// 7: 构造方法可以给属性赋值,通过参数传入初始化属性的值
// 8: 构造方法可以初始化调用执行一些成员方法
// 9: 如果父类中定义了构造方法 子类中必须有构造方法,并且构造方法的第一行调用父类的构造
方法之一
// 10: 继承中 子类在创建对象的时候,会向上连带着调用父类的构造方法
public Student(){
stu_id = new Random ().nextInt (Integer.MAX_VALUE);
System.out.println ("Student 空参数构造方法");
}
public Student(String stu_name, int stu_id){
this.stu_id = stu_id;
this.stu_name = stu_name;
System.out.println ("Student 重载的有参数构造方法");
}
public Student(String stu_name){
this.stu_id = 100;
this.stu_name = stu_name;
System.out.println ("Student 重载的有参数构造方法");
}// 创建公共的方法来调用使用私有的属性
// 返回属性
public int getStu_age(){
return stu_age;
}
// 传入参数给属性赋值
public void setStu_age(int stu_age){
this.stu_age = stu_age;
}
public void read(){
System.out.println ("UNStudent read book");
}
}
// SuperClass
class UNStudent extends Student{
public UNStudent(){
// 必须调用一个父类带参数的构造方法
super ("stu_name", 10);
System.out.println ("UNStudent 有参数构造方法");
}
public void showInformation(){
// 子类可以直接使用 父类中非私有的属性以及方法
System.out.println ("stu_name:" + stu_name);
System.out.println ("stu_age:" + getStu_age ());
System.out.println ("id:" + id);
System.out.println ("score:" + score);
}
public void read(){
System.out.println ("UNStudent read 《人有人的用处》");
}
public static void main(String[] args){
System.out.println ("字符串");
System.out.println (10);
System.out.println (1.123d);
System.out.println (true);
System.out.println (new UNStudent ());
System.out.println ('a');
System.out.println (1.234f);
System.out.println (100l);// 创建子类对象
UNStudent unStudent = new UNStudent ();
// 创建对象变量名 所有的对象的引用地址都是存储在同类型的对象变量中
Student student1;
// student 与 unstudent 变量是不同的类型 但是有继承关系
// 存储的都是同一个对象的地址
student1 = unStudent;
System.out.println (student1 + "\n" + unStudent);
// 创建第二个子类对象
MidStudent midStudent = new MidStudent ();
Student student2 = midStudent;
unStudent.read ();
midStudent.read ();
// 子类对象转型之后,调用子类重写过的方法还是子类的
student1.read ();
student2.read ();
ManageStudent.studentReadBook (unStudent);
ManageStudent.studentReadBook (midStudent);
}
}
class ManageStudent{
// public static void studentReadBook(UNStudent unstu){
// unstu.read ();
// }
// public static void studentReadBook(MidStudent midstu){
// midstu.read ();
// }
// 有了继承 与 方法重写
// 以父类作为参数类型,所有的子类对象可以作为参数传入
// 方法体中调用子类重写过的方法
public static void studentReadBook(Student stu){
stu.read ();
}
}
class MidStudent extends Student{
@Override// 注解 - 检查重写是否正确
public void read(){
System.out.println ("MidStudent read 《红楼梦》");}
}