面向对象特征之二:继承性
一、 继承性的好处:
(1)减少了代码的冗余,提高了代码的复用性
(2)便于功能的扩展
(3)为之后多态性的使用,提供了前提
二、继承性的格式: class A extends B{ }
A:子类、派生类、subclass
B:父类、超类、基类、superclass
2.1 体现,一旦子类A继承父类B之后,子类A就获取父类B中声明的所有的属性和方法
特别的,父类中声明为private的属性或方法,子类继承父类之后,仍然认为获取了父类中私有的结构。
2.2 子类继承父类以后,还可以声明自己持有的属性或方法,实现功能的扩展
三、Java中关于继承性的规定:
- 一个类可以被多个子类继承
- Java类中的单继承性:一个类只能有一个父类
- 子父类是相对的概念
- 子类直接继承的父类:直接父类,间接继承的父类称为:间接父类
- 子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法
四、 Object类
-
如果我们没有显式的声明一个类的父类的话,则此类继承于java.lang.Object类
-
所有的java类(除java.lang.Object类)都直接或间接的继承于java.lang.Object类
-
意味着,所有的Java类具有java.lang.Object类声明的功能
五、练习
练习1
练习2
ManKind.java
package extends_test;
public class ManKind {
private int sex;
private int salary;
public void manOrWoman(){
if (sex == 1){
System.out.println("man");
}else if (sex == 0){
System.out.println("woman");
}
}
public void employeed(){
if (salary == 0){
System.out.println("no job");
}else if (salary != 0){
System.out.println("job");
}
}
public ManKind() {
}
public ManKind(int sex, int salary) {
this.sex = sex;
this.salary = salary;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
Kids.java
package extends_test;
public class Kids extends ManKind{
private int yearsOld;
public Kids(){
}
public Kids(int yearsOld){
this.yearsOld = yearsOld;
}
public void printAge(){
System.out.println("当前年龄为:" + yearsOld);
}
public int getYearsOld() {
return yearsOld;
}
public void setYearsOld(int yearsOld) {
this.yearsOld = yearsOld;
}
}
KidsTest.java
package extends_test;
public class KidsTest {
public static void main(String[] args) {
Kids someKid = new Kids(12);
someKid.printAge();
someKid.setSalary(0);
someKid.setSex(1);
someKid.employeed();
someKid.manOrWoman();
}
}
练习3
Circle.java
package extends_test;
public class Circle {
private double radius;
public Circle() {
}
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public double findArea(){
return Math.PI*radius*radius;
}
}
Cylinder.java
package extends_test;
public class Cylinder extends Circle {
private double length;
public Cylinder() {
}
public Cylinder(double length) {
this.length = length;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double findVolume(){
return findArea()*length;
}
}
CylinderTest.java
package extends_test;
public class CylinderTest {
public static void main(String[] args) {
Cylinder c = new Cylinder(10);
c.setRadius(3);
System.out.println("当前半径为:" + c.getRadius());
System.out.println("当前高为:"+c.getLength());
System.out.println("当前圆的面积为:"+c.findArea());
System.out.println("当前圆柱体积为:"+c.findVolume());
}
}
方法的重写(Override/Overwrite)
1.定义:
在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
2.要求:
(1) 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
(2) 子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
(3) 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限
(子类不能重写父类中声明为private权限的方法)
(4)子类方法抛出的异常不能大于父类被重写方法的异常
3.注意
子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static(不是重写),因为static方法是属于类的,子类无法覆盖父类的方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h8HeKycO-1617891406813)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20210408164339324.png)]
关键字:super
-
super理解为:父类的
-
super可以用来调用:属性、方法、构造器
-
super的使用
(1)我们可以在子类的方法或者构造器中,通过使用“super.属性”或“super.方法”的方式,显式的调用父类中声明的属性或者方法。但是通常情况下,我们习惯省略“super.”
(2)特殊情况,当子类和父类定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用“super.属性”的方式,表明调用的是父类中声明的属性。
(3)特殊情况,当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用“super.方法”的方式,表明调用的是父类中声明的方法。 -
super调用构造器
(1)我们可以在子类的构造器中显式的使用**“super(形参列表)”**的方式,调用父类中声明的指定的构造器。
(2)Error: java: 对super的调用必须是构造器中的第一个语句
(3)我们在类的构造器中,针对于“this(形参列表)”或“super(形参列表)”只能二选一,不能同时出现。
(4)在构造器首行,没有显式的声明“this(形参列表)”或“super(形参列表)”,则默认调用的是父类中空参的构造器super( )
(5)在类的多个构造器中,至少有一个类的构造器使用了”super(形参列表)“调用父类中的构造器。
子类对象的实例化过程
1.从结果上看(继承性)
子类继承父类之后,就获取了父类中声明的属性或方法
创建子类的对象,在堆的空间中,就会加载所有父类中声明的属性。
2.从过程上看
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接地调用其父类地构造器,进而调用父类的父类的构造器,直到调用了java.lang.Object类中空参的构造器为止,正因为加载过所有的父类的结构,所以才可以看到内存中有父类的结构,子类对象才可以考虑调用。
明确:虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象
实验
Account.java
package supertest;
public class Account {
private int id;
private double balance;
private double annualinterestRate;
public Account() {
}
//构造器
public Account(int id, double balance, double annualinterestRate) {
this.id = id;
this.balance = balance;
this.annualinterestRate = annualinterestRate;
}
//getter,setter
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public double getBalance() { return balance; }
public void setBalance(double balance) { this.balance = balance; }
public double getAnnualinterestRate() { return annualinterestRate; }
public void setAnnualinterestRate(double annualinterestRate) {this.annualinterestRate = annualinterestRate; }
//方法
public void withdraw(double amount){ //取钱
if (balance<=0 || balance< amount){
System.out.println("您想要取款"+amount+",当前余额为:"+balance+",取款失败");
}else {
balance-=amount;
System.out.println("您想要取款"+amount+",成功取款"+amount+",您的账户余额为:"+ balance);
}
}
public void deposit(double amount){//存钱
if (balance>0) {
balance += amount;
System.out.println("您想要存款"+amount+",成功存入" + amount + ",您的账户余额为:" + balance);
}
}
}
CheckAccount.java
package supertest;
public class CheckAccount extends Account{
private double overdraft;//透支额 ----属性
//构造器
public CheckAccount(){ }
public CheckAccount(int id, double balance, double annualinterestRate,double overdraft){
super(id, balance, annualinterestRate);
this.overdraft= overdraft;
}
public double getOverdraft() {
return overdraft;
}
public void setOverdraft(double overdraft) {
this.overdraft = overdraft;
}
//重写withdraw方法
@Override
public void withdraw(double amount){
if (amount<= getBalance()){
setBalance(getBalance()-amount);
System.out.println("您想要取款"+amount+",成功取出" + amount + ",您的账户余额为:" + getBalance()+",您可透支金额为:"+overdraft);
}else if (amount>getBalance()){
if (overdraft>= (amount-getBalance())){
overdraft=overdraft+getBalance()-amount;
System.out.println("您想要取款"+amount+",取款成功,当前余额为:0.0,透支金额:"+(amount-getBalance())+",剩余可透支的金额为:"+overdraft);
setBalance(0);
}else {
System.out.println("您想要取款"+amount+",超出可透支金额!");
}
}
}
}
AccountTest.java
package supertest;
public class AccountTest {
public static void main(String[] args) {
Account a = new Account(1122,20000,0.045);
a.withdraw(30000);
a.withdraw(2500);
a.deposit(3000);
System.out.println("***********************************************");
CheckAccount a1 = new CheckAccount(1123,20000,0.045,5000);
a1.withdraw(5000);
a1.withdraw(18000);
a1.withdraw(3000);
}
}