继承
概述:
子承父业就是继承,父类的资源可以给子类使用。
java中的继承指的就是一个类的资源可以被另一个类使用这两个类的关系就是继承关系。
子类继承父类之后有什么效果?
子类拥有了父类的非私有成员(成员变量、成员方法)
继承的使用场景
多个类中存在相同的属性和行为时,可以将这些内容提取出来放到一个新的类中,让这些类和新类产生父子关系,实现代码复用
例如: 创建一个动物类 让猪类和狗类继承动物类的属性
如何产生继承关系:
使用一个类通过关键字extends去连接另一个类从而产生继承关系
子类继承父类的格式:
类A extends 类B { 类A的内容 }
注意事项:
类A 是子类 【新定义的事物】
类B 是父类 【父类肯定已经存在】
类B的公开的资源类A就可以使用不用自己定义了
代码示例
/**
* 定义一个父类 Parent
*/
public class Parent {
//成员变量
private String name;
private int age;
//构造方法
public Parent() {
}
public Parent(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 void show() {
System.out.println("我是父类的方法!!");
}
}
/**
*Child: 子类 、派生类
* Parent:父类、基类、超类
*/
public class Child extends Parent{
//Java中,子类只能继承父类的非私有成员(成员变量,成员方法)
// public void study() {
// System.out.println(name+"正在学习!"); //会报错因为name为私有属性
// }
}
/**
*测试类
*/
public class Test {
//main函数是程序的主入口,所有的代码都是从这里开始执行的
public static void main(String[] args) {
//创建对象
Child c = new Child();
//给父类中成员变量设置值
c.setName("张三");
c.setAge(20);
System.out.println(c.getName());
System.out.println(c.getAge());
System.out.println("---------------");
//Java中,子类只能继承父类的非私有成员(成员变量,成员方法)
// c.study();
c.show(); //继承自父类
}
}
继承的优缺点
优点:
1、功能复用
直接将已有的属性和行为继承过来,实现了功能的复用,节省了大量的工作
2、便于扩展新功能
在已有功能的基础上,更容易建立、扩充新功能
3、结构清晰,简化认识
同属于一个继承体系的相关类,他们之间结构层次清晰,简化了人们对代码结构的认识
3、易维护性
不同类之间的继承关系,让这些事物之间保持一定程度的一致性,大大降低了维护成本
缺点
1、打破了封装性
父类向子类暴露了实现细节,打破了父类对象的封装性
2、高耦合性
类与类之间紧密的结合在一起,相互依赖性高
Java中使用成员变量的规则
遵循就近原则,局部位置有就使用,
没有就去本类成员位置找,有就使用
没有就去父类成员位置找,有就使用,没有就报错
继承关系中成员变量
使用原则:
不同名的变量:
父类对象只能访问自己拥有的变量,子类独有的变量父类对象无法访问
同名的变量:
父类对象只能访问自己拥有的变量的值,子类对象优先访问自己拥有的变量的值
子类对象可以访问所有的变量,父类对象只能访问自己的属性,同名的变量的时候子类对象想
要访问父类的变量的值使用关键字super来访问
继承关系中成员变量的使用特点
this.变量名 访问全局变量
super.变量名 访问父类变量
继承关系中成员变量使用的结论
1、查找变量的原则
就近原则
2、查找变量的顺序
局部变量 ----> 成员变量 ----> 父类 ----> 更高的父类 …Object
3、访问父类变量的方式
super.父类变量名;
super
当前对象父类的引用(父类内存空间的标识)
对象初始化顺序
先初始化父类内容,在初始化子类内容
代码示例
父类:
public class Person {
String name;
int age;
}
子类:
public class Woman extends Person{
int age = 100;// 和父类同名的属性
String color;// 独有的属性【不同名的属性】
public void show1() {
System.out.println(this.age);// 100
// 子类对象非要访问父类的属性age的值
System.out.println(super.age);// 0
}
}
测试类:
public class TestWoman {
public static void main(String[] args) {
Woman woman = new Woman();
System.out.println(woman.name);// null 父类的值
System.out.println(woman.age);// 100 子类的值
System.out.println(woman.color);// null 子类的值
woman.show1();
System.out.println("===============");
//创建父类对象
Person person = new Person();
System.out.println(person.age);// 0 父类的
System.out.println(person.name);// null 父类
// System.out.println(person.color);// 报错 子类的color,父类无法使用子类特有的
}
}
this和super的区别
this
本质: 对象
用法: 从本类开始找
super
本质: 父类内存空间的标识
用法: 从父类开始找
this:当前调用对象
super:当前调用对象的父类引用
使用:
this:可以访问当前对象的所有的资源
super:只能访问当前调用对象的父类拥有的资源
this:在类中的其他构造方法中可以调用自己的构造 this()
super:在类中的构造方法中可以调用父类的构造方法 super(实参)
如果没有调用父类的任何构造方法 系统偷偷补super()
注意事项:
1、this()和super()不能同时出现
2、this()和super()使用的时候必须在第一行
代码示例 (在下方)
继承中的成员方法
使用原则:
父类对象只能使用自己的方法,子类对象可以使用所有的方法
同名方法:
子类对象优先执行自己拥有的方法的方法体
继承关系中成员方法使用的结论
查找方法的原则
就近原则
查找方法的顺序
本类 ----> 父类 ----> 更高的父类 …Object
访问父类方法的方式
super.父类变量名;
定义重名方法的前提
父类功能不能完全满足实现需求,扩展父类功能
父类功能已过时,重新实现父类功能
继承关系中构造方法的使用
概述:
子类不能继承父类的构造方法(因为构造方法是用来实例化对象,父类的构造方法用来实例化父类对象,所以不能被继承),但是子类可以调用父类的构造方法,主要作用在子类对象空间中开辟空间加载父类描述的属性和方法的标记。
子类对象的创建优先加载父类的构造。
继承关系中子父类构造方法的使用
创建子类对象时,优先调用父类构造方法
所有子类构造方法的第一行,隐含语句super(),用于调用父类的默认无参构造
结论:
-
子类所有构造方法的第一行都有一个默认的super()用来访问父类的无参构造方法
-
如果父类没有无参构造,可以通过super(参数)的形式访问父类的带参构造
代码示例
父类:
public class Person {
private String name;
private int age;
private int a = 100;
//getter 和 getter 方法
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 getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public Person(String name, int age, int a) {
super();
this.name = name;
this.age = age;
this.a = a;
}
public Person() {
super();
}
}
子类:
public class Son extends Person{
private int a = 500;
private int b = 1000;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
public Son() {
super();// 调用了父类的空参构造方法
}
public Son(int a, int b) {
//this();// 调用自己的构造方法
super();
this.a = a;
this.b = b;
}
public Son(String name, int age, int a, int a2, int b) {
super(name, age, a);
a = a2;
this.b = b;
}
public void show() {
System.out.println(this.getA());// 500
System.out.println(super.getA());// 100
System.out.println(this.getName());// null
System.out.println(super.getName());// null
}
}
测试类:
public class TestSon {
public static void main(String[] args) {
Son son = new Son();
son.show();
}
}
继承方式
编程领域继承关系有多种:
1、单继承:一个类只能继承一个类
2、多继承:一个类同时继承了多个类
3、多层继承:一个类继承了另一个类的同时被第三个类继承
java中支持的继承只有:单继承和多层继承。
(接口可以多继承)
父类私有的资源子类不能继承。
练习
程序员类:
属性:姓名 年龄 工号 工资
行为:工作
经理类:
属性:姓名 年龄 工号 工资 奖金
行为:工作
分析:
类中有相同的属性,每次书写不同类的时候的都要重复的书写,比较烦,就可以把相同的属性提出来放到一个类中,其他类继承这个类这些属性就不需要重复的书写并且可以使用。
代码示例:
父类:
package com.ujiuye.demo;
public class Employee {
// 姓名
private String name;
// 年龄
private int age;
// 工号
private String id;
//工资
private double salary;
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 String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Employee(String name, int age, String id, double salary) {
super();
this.name = name;
this.age = age;
this.id = id;
this.salary = salary;
}
public Employee() {
super();
}
public Employee(int age, String id, double salary) {
super();
this.age = age;
this.id = id;
this.salary = salary;
}
}
程序员子类:
public class Coder extends Employee{
public void work() {
System.out.println("程序员每天都在写代码!");
}
// 有参构造能不能提供?不能,类没有自己的属性
// 空参构造有没有? 有 不止一个 空参构造可以的调用不同的 父类构造
public Coder() {
super();// 子类空参调用了父类的空参构造
}
public Coder(String name, int age, String id, double salary) {
// 子类空参调用了父类的满参构造
super(name, age, id, salary);
}
public Coder( int age, String id, double salary) {
// 子类空参调用了父类的满参构造
super( age, id, salary);
}
}
经理子类:
public class Manager extends Employee{
private int bonus;
public int getBonus() {
return bonus;
}
public void setBonus(int bonus) {
this.bonus = bonus;
}
public Manager() {
super();
}
public Manager(String name, int age, String id, double salary) {
super(name, age, id, salary);
}
public Manager(String name, int age, String id, double salary, int bonus) {
super(name, age, id, salary);
this.bonus = bonus;
}
public Manager(int bonus) {
super();
this.bonus = bonus;
}
public void work() {
System.out.println("项目经理拿着高工资!");
}
}
测试类:
public class TestEmployee {
public static void main(String[] args) {
Coder coder = new Coder();
Manager manager = new Manager();
System.out.println(coder.getName());
System.out.println(coder.getAge());
System.out.println(coder.getId());
System.out.println(coder.getSalary());
coder.work();
System.out.println(manager.getName());
System.out.println(manager.getAge());
System.out.println(manager.getId());
System.out.println(manager.getSalary());
System.out.println(manager.getBonus());
manager.work();
}
}