1.面向对象的第二特征:继承
继承的好处:
1)减少了代码的冗余,提高了代码的复用性
2)便于功能的扩展
3)为之后多态性的使用,提供了前提
2.继承的基本概念
package com.yl.pdfdemo.day04.p1;
/**
* @Author wfj
* @Date 2021/3/29
* @Description
* @Version 1.0
*/
public class Creature {
public void run() {
System.out.println("run...");
}
}
package com.yl.pdfdemo.day04.p1;
/**
* @Author wfj
* @Date 2021/3/29
* @Description
* @Version 1.0
*/
public class Person extends Creature{
String name;
private int age;
public Person() {
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public Person(String name,int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println("eat...");
}
public void say() {
System.out.println("say...");
}
}
package com.yl.pdfdemo.day04.p1;
/**
* @Author wfj
* @Date 2021/3/29
* @Description
* @Version 1.0
*/
public class Student extends Person{
// String name;
// int age;
int grade;
public Student() {
}
public Student(String name,int age,int grade) {
this.name = name;
setAge(age);
this.grade = grade;
}
// public void eat() {
// System.out.println("eat..");
// }
//
// public void say() {
// System.out.println("say...");
// }
public void study() {
System.out.println("study...");
}
}
package com.yl.pdfdemo.day04.p1;
/**
* @Author wfj
* @Date 2021/3/29
* @Description 面向对象的特征之二:继承
* @Version 1.0
*/
public class ExtTest1 {
public static void main(String[] args) {
/**
* 一、继承的好处
* 1.减少了代码的冗余,提高了代码的复用性
* 2.便于功能的扩展
* 3.为之后多态性的使用,提供了前提
*
* 二、继承的格式:class A extends B{}
* A:子类,派生类,subclass
* B:父类,超类,基类,superclass
*
* 2.1体现:一旦子类A继承了父类B以后,子类A中就获取了父类中声明的所有属性和方法(包括私有的)
* 父类中声明的私有的属性和方法,子类继承父类后,仍然认为获取了父类中私有的属性和方法
* 只是因为封装性的影响,使得之类不能直接调用父类的的结构而已
*
* 2.2 子类继承父类以后,还可以声明自己持有的属性或者方法,实现功能的拓展
*
* 三、java中关于继承的规定
* 1.一个类可以被多个子类继承
* 2.一个类只能有一个父类:单继承
* 3.子父类是相对的概念
* 4.子类直接继承的父类,称为直接父类,间接继承的父类称为间接父类
* 5.子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法
*
* 四、1.如果我们没有显式的声明一个类的父类的话,则此类继承于java.lan.Object
* 2.所有的java类(除java.lan.Object类)外,都直接或间接继承于java.lang.Object
* 3.意味着,所有的java都具有Object的java.lan.Objec类声明的功能
* */
Person person = new Person();
person.setAge(19);
person.say();
Student student = new Student();
student.setAge(10);
student.name = "xiao";
student.say();
student.study();
student.run();
}
}
3.方法重写使用
package com.yl.pdfdemo.day04.p2;
/**
* @Author wfj
* @Date 2021/3/29
* @Description
* @Version 1.0
*/
public class Person {
String name;
int age;
public Person() {
}
public Person(String name,int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println("eat...");
}
public void say() {
System.out.println("say...");
}
}
package com.yl.pdfdemo.day04.p2;
/**
* @Author wfj
* @Date 2021/3/29
* @Description
* @Version 1.0
*/
public class Student extends Person{
String gender;
public Student() {
}
public Student(String gender) {
this.gender = gender;
}
public void study() {
System.out.println("study...");
}
public void eat() {
System.out.println("student eat...");
}
}
package com.yl.pdfdemo.day04.p2;
/**
* @Author wfj
* @Date 2021/3/29
* @Description 方法重写
* @Version 1.0
*/
public class PersonTest {
public static void main(String[] args) {
/**
* 方法的重写:(overrite / overwrite)
* 1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖
*
* 2.应用:重写后,当创建子类对象后,通过子类对象调用子父类中同名同参数的方法时,实际执行的是子类中的那个方法
*
* 面试题:重载和重写有什么区别?
*
* 概念:
* 重载=》在同一个类中,可以声明多个方法名称相同,形参列表不同的方法,构造器也可以进行重载
* 重写=》子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
* 重载:不表现多态性
* 重写:表现为多态性
*
* 3.重写的规定:
* 方法的声明: 访问权限修饰符 返回值类型 方法名(形参列表)throws 异常类型{方法体}
* 约定俗称:子类中的叫重写的方法,父类中叫被重写的方法
* 3.1 子类重写的方法的方法名和形参列表和父类的被重写方法的方法名和形参列表相同
*
* 3.2 子类重写的方法的权限访问修饰符不小于父类被重写方法的权限访问修饰符
* 》特殊情况,子类不能重写父类中声明为private的方法
*
* 3.3 返回值类型
* 》如果父类中被重写的方法的返回值类型是void,那么子类中重写的方法返回也必须是void
* 》父类中被重写都方法的返回值的类型是A,那么子类中重写的方法的返回值可以是A类,或者A类的子类
* 》如果父类中被重写的方法的返回值类型是基本数据类型,那么子类中重写的方法返回也必须是对应的基本数据类型
*
* 3.4 子类重写的方法抛出的异常类型不大于父类中被重写方法说抛出的异常类型
*
* 子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static(不是重写)
*/
Student student = new Student("男");
student.eat();
student.say();
student.study();
}
}
4.super关键字的使用
package com.yl.pdfdemo.day04.p3;
/**
* @Author wfj
* @Date 2021/3/29
* @Description
* @Version 1.0
*/
public class Person {
String name;
int age;
int id = 100;
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(String name,int age) {
//这里用this调用了带有一个参数的构造器
this(name);
this.age =age;
}
public void eat() {
System.out.println("eat...");
}
public void say() {
System.out.println("say...");
}
public void sing() {
System.out.println("sing...");
}
}
package com.yl.pdfdemo.day04.p3;
/**
* @Author wfj
* @Date 2021/3/29
* @Description
* @Version 1.0
*/
public class Student extends Person {
String gender;
int id = 101;
public Student() {
}
public Student(String name,int age,String gender) {
super(name,age);
this.gender = gender;
}
public Student(String gender) {
this.gender = gender;
}
@Override
public void eat() {
System.out.println("student eat...");
}
public void study(){
System.out.println("student study...");
}
public void show() {
// 会在当前类找有没有这个属性,有的话直接用,没有的话就再去父类找
System.out.println("name="+name+",age="+age);
// 如果父类和子类存在相同的属性,那么子类默认会使用自己的属性值
System.out.println("子类id="+id); // 101(省略了this)
System.out.println("父类id="+super.id); // 100
eat();// 相当于this.eat()
super.eat(); // 调用父类的eat
this.sing(); // 会在本类找该方法,如果没有就去父类找
super.sing();// 调用父类方法
sing();//会在本类找该方法,如果没有就去父类找
}
}
package com.yl.pdfdemo.day04.p3;
/**
* @Author wfj
* @Date 2021/3/29
* @Description super关键字的使用
* @Version 1.0
*/
public class SuperTest {
public static void main(String[] args) {
/**
* super的使用
* 1.super理解为:父类的
* 2.super可以用来调用:属性,方法,构造器
*
* 3.super的使用:调用属性或者方法
*
* 3.1 我们可以在子类的方法或者构造器中,通过super.属性或者super.方法的方式,显式的调用父类中声明的属性或方法,但是通常省略super
*
* 特别地: 1)当子类和父类定义了相同名称的属性时,我们要在子类中调用父类中声明的属性,就必须要用super来调用
* 2)当子类重写父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须使用super来调用
*
*4.super调用构造器
* 1) 我们可以在子类的构造器中显式的使用super(形参列表)的形式,调用父类中指定的构造器
* 2) super(形参列表)的使用,必须声明在子类的首行
* 3) 我们在类的构造器中,this(形参列表),super(形参列表)只能出现一个,不能同时出现
* 4)在构造器首行,没有显式的声明this(形参列表),super(形参列表),则默认调用的父类中空参的构造器
* 5) 在类的多个构造器中,至少有一个类的构造器使用了super(形参列表),调用父类的构造器
*
* 5.子类对象实例化过程
* 1) 从结果上看:(继承性)
* 子类继承父类以后,就获取了父类中声明的属性或方法
* 创建子类的对象,在堆空间中,就会加载父类的所有的属性
*
* 2)从过程上看:
* 当我们通过子类的构造器创建子类对象时,我们一定会间接或者直接的调用了父类的构造器,进而调用父类的父类的构造器
* 直到调用了java.lang.Object的空参构造器为止,正因为加载过所有的父类的结构,所以才看到内存中有父类的中的结构,
* 子类对象才可以进行调用
*/
Student student = new Student();
student.show();
System.out.println("++++++++++++++++++++++=");
Student s1 = new Student("小明",18,"男");
s1.show();
}
}
5.练习1
package com.yl.pdfdemo.day04.p1;
/**
* @Author wfj
* @Date 2021/3/29
* @Description
* @Version 1.0
*/
public class Circle {
private double radius;
public Circle() {
radius = 0.1;
}
public void setRadius(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public double findArea() {
return Math.PI * radius * radius;
}
}
package com.yl.pdfdemo.day04.p1;
/**
* @Author wfj
* @Date 2021/3/29
* @Description
* @Version 1.0
*/
public class Cylinder extends Circle {
private double length;
public Cylinder() {
length = 1;
}
public void setLength(double length) {
this.length = length;
}
public double getLength() {
return length;
}
// 求圆柱体积
public double findVolume() {
return findArea() * length;
}
}
package com.yl.pdfdemo.day04.p1;
/**
* @Author wfj
* @Date 2021/3/29
* @Description 继承练习
* @Version 1.0
*/
public class CycleTest {
public static void main(String[] args) {
Cylinder cylinder = new Cylinder();
cylinder.setRadius(2.1);
cylinder.setLength(5);
System.out.println("圆柱的体积为:" + cylinder.findVolume());
}
}
6.练习2
package com.yl.pdfdemo.day04.p1;
/**
* @Author wfj
* @Date 2021/3/29
* @Description
* @Version 1.0
*/
public class ManKind {
private int sex;
private int salary;
public void setSex(int sex) {
this.sex = sex;
}
public int getSex() {
return sex;
}
public void setSalary(int salary) {
this.salary = salary;
}
public void manOrWoman() {
if (sex == 1) {
System.out.println("man");
} else {
System.out.println("woman");
}
}
public void employee() {
if (salary == 0) {
System.out.println("no job");
} else {
System.out.println("job");
}
}
}
package com.yl.pdfdemo.day04.p1;
/**
* @Author wfj
* @Date 2021/3/29
* @Description
* @Version 1.0
*/
public class Kids extends ManKind {
private int yearsOid;
public Kids(){
}
public Kids(int yearsOid) {
this.yearsOid = yearsOid;
}
public void printAge() {
System.out.println(yearsOid);
}
}
package com.yl.pdfdemo.day04.p1;
/**
* @Author wfj
* @Date 2021/3/29
* @Description 继承练习
* @Version 1.0
*/
public class KidsTest {
public static void main(String[] args) {
Kids kids = new Kids();
kids.setSex(1);
kids.setSalary(1000);
kids.manOrWoman();
kids.employee();
}
}
7.练习3
package com.yl.pdfdemo.day04.p3;
/**
* @Author wfj
* @Date 2021/3/30
* @Description
* @Version 1.0
*/
public class Account {
private int id; // 账号
private double balance; //余额
private double annualInterestRate; // 年利率
public Account() {
}
public Account (int id,double balance,double annualInterestRate) {
super();
this.id = id;
this.balance = balance;
this.annualInterestRate = annualInterestRate;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setBalance(double balance) {
this.balance = balance;
}
public double getBalance() {
return balance;
}
public void setAnnualInterestRate(double annualInterestRate) {
this.annualInterestRate = annualInterestRate;
}
public double getAnnualInterestRate() {
return annualInterestRate;
}
//返回月利率
public double getMonthlyInterest() {
return annualInterestRate / 12;
}
//取钱
public void withdraw(double amount) {
if (balance >= amount) {
balance -= amount;
return;
}
System.out.println("余额不足");
}
//存钱
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
}
package com.yl.pdfdemo.day04.p3;
/**
* @Author wfj
* @Date 2021/3/30
* @Description
* @Version 1.0
*/
public class CheckAccount extends Account{
private double overDraft; // 可透支限额
public void setOverDraft(double overDraft) {
this.overDraft = overDraft;
}
public double getOverDraft() {
return overDraft;
}
public CheckAccount(int id,double balance,double annualInterestRate,double overDraft) {
super(id,balance,annualInterestRate);
this.overDraft = overDraft;
}
//重写取钱方法
@Override
public void withdraw(double amount) {
// getBalance() -= amount; 错误写法
if (getBalance() >= amount) { // 余额足够消费
//方式一
//setBalance(getBalance() - amount);
// 方式二
super.withdraw(amount);
} else if (overDraft >= amount - getBalance()) { // 透支额度+余额足够消费
overDraft -= (amount - getBalance());
setBalance(0);
} else {
System.out.println("超过可透支限额");
}
}
}
package com.yl.pdfdemo.day04.p3;
/**
* @Author wfj
* @Date 2021/3/30
* @Description
* @Version 1.0
*/
public class AccountTest {
public static void main(String[] args) {
Account account = new Account(111,20000,0.045);
account.withdraw(30000);
System.out.println("您的余额为:" + account.getBalance());
account.withdraw(2500);
System.out.println("您的余额为:" + account.getBalance());
account.withdraw(1000);
System.out.println("您的余额为:" + account.getBalance());
System.out.println("月利率为:" + (100 * account.getMonthlyInterest()) + "%");
}
}
package com.yl.pdfdemo.day04.p3;
/**
* @Author wfj
* @Date 2021/3/30
* @Description
* @Version 1.0
*/
public class CheckAccountTest {
public static void main(String[] args) {
CheckAccount account = new CheckAccount(1122,2000,0.045,5000);
account.withdraw(5000);
System.out.println("您的账户余额为:" + account.getBalance());
System.out.println("您的可透支额度为:" + account.getOverDraft());
account.withdraw(1800);
System.out.println("您的账户余额为:" + account.getBalance());
System.out.println("您的可透支额度为:" + account.getOverDraft());
account.withdraw(3000);
System.out.println("您的账户余额为:" + account.getBalance());
System.out.println("您的可透支额度为:" + account.getOverDraft());
}
}