9、继承
(1)为什么使用继承
-
代码复用(多个子类中有共同的方法或者属性)
-
实现多态(多个子类为了满足自己的需要将父类的方法重写)
(2)如何使用继承
-
[访问修饰符] class 子类名 extends 父类名 {
子类成员变量
子类成员方法
}
(3)子类可以继承父类的哪些内容
-
可以继承public和protected修饰的属性和方法,不论父类子类是否在同一个包里
-
可以继承默认访问修饰符的属性和方法,但是父类和子类必须在同一个类里
-
无法继承父类的构造方法d
(4)继承中的构造
-
子类继承了父类除构造方法的所有成员,包括实例属性和实例方法
-
子类可以新增自己的属性和方法,从而达到扩展自己的目的
-
谁定义的属性,由谁来初始化,也就是子类的构造方法中用super将父类定义的属性需要初始化的值传递给父类的构造方法,子类自己定义的新的属性在自己的构造方法中初始化。
-
new子类的时候父类new了没?()
-
答:new了
-
-
new子类时是否调用了父类的构造方法
-
答:调用了
-
-
new子类是,先调用子类的构造函数,在调用父类的构造函数
-
new子类时,先执行父类的构造函数,在执行子类的构造函数
9.1方法重写override
(1)what(什么是方法重写)
-
在继承关系中子类的方法名称,参数,返回值类型与父类的方法名称,参数,返回值类型相同;范围修饰符不允许缩小;称为方法重写。
(2)why(为什么使用方法重写)
-
子类从父类继承的方法不能满足子类的需要,所以子类需要重新定义从父类继承的方法,从而达到满足自己的需要。
(3)where(在哪使用方法重写)
-
在子类中,如果继承而来的方法不满足需要,就可以重写父类方法。
(4)how(怎样使用方法重写)
-
将继承而来的不满足需要的父类方法重新定义。
9.3@Override注解
@Override是一个注解,它表示被重写的方法
@Override
public void print() {
System.out.println("使用彩色打印机");
}
9.4 super的用法
super表示调用父类成员,有两种用法
(1)调用父类的构造函数,放在子类构造函数的第一行
public Student(int age,String name){
super(age);
this.name = name;
}
(2)普通方法中调用父类的实例属性或者实例方法
public void print(){
super.print();
super.name = "小王";
}
9.5 Object类
Object类是所有的类的父类,一个类总是直接或者间接继承Object类,Object是类的最高层。
public class SayHello{
}
public class SayHello extends Object{
}
//两种不同的写法,表达的意思是一样的。如果一个类没有显示继承Object类,默认继承Object类
9.6 toString方法
public class Student{
public static void main(String[] args){
Student s = new Student();
//默认调用toString方法
System.out.println(s);
System.out.println(s.toString());
}
}
***************************************************
//运行结果
com.xiaowei.demo0915.Student@4f3f5b24
com.xiaowei.demo0915.Student@4f3f5b24
重写toString方法
public class Student {
//重写toString方法
@Override
public String toString(){
return "你好";
}
public static void main(String[] args) {
Student s = new Student();
System.out.println(s);
System.out.println(s.toString());
}
}
*****************************************
E:\实习\ycdl\out\production\ycdl com.xiaowei.demo0915.Student
你好
你好
Process finished with exit code 0
final关键字
final可以修饰类,方法,以及属性
-
final修饰的类不能被继承
-
final修饰的方法不能被重写
-
final修饰的属性也不能修改值,即使修改为跟原来一样的数据,也不可以。
多态
what(什么是多态)?
多态是多种形态,表现形式有两种,第一种是方法重载,第二种是方法重写。
why(为什么使用多态)?
多态就是使用同样的方法完成不同的操作,通过一个父类引用到多个子类
where(在哪用多态)?
要表述一种方法实现多种操作的时候,就可以使用重写(动态多态)
一种方法返回不同的数据,可以使用重写(静态多态)
how(怎么用多态)?
多态可以是方法重载,也可以是方法重写
重载例如System.out.println()可以输出类型不同的数据。
重写:有几个子类重写的方法就有几个多态,一种方法完成不同的操作。
父类引用指向子类对象(多态的核心)
//父类的引用d1指向子类的对象
Department d1 = null;
d1 = new PersonnelDept(20, "人事部", 5, "负责招聘", "王平", 6);
d1.printDetail();//父类的引用指向哪个子类的对象,就调用哪个子类的方法,此处调用的是人事部的printDetail方法
d1 = new ResearchDept(10, "研发部", 20, "负责开发", "王宁", "全栈");
d1.printDetail();//父类的引用指向哪个子类的对象,就调用哪个子类的方法,此处调用的是研发部的printDetail方法
//子类的引用r指向父类的对象
ResearchDept r = (ResearchDept) new Department();
r.printDetail();
(1)父类引用指向子类对象可直接赋值
(2)子类引用不能指向父类对象,除非强制类型转换,但是会造成数据的丢失
就如同基本数据类型中,将int类型转换为short类型一样。
向上转型
子类向父类转换成为向上转型
<父类类型> <引用变量名> = new <子类类型>();
例如:Pet pet = new Dog();
向下转型
父类向子类转换称为向下转型。
<子类类型> <引用变量名> = (<子类类型>) new <子类类型>();
例如:Dog dog = (Dog) new Pet();
重要
父类引用指向子类对象,父类引用只能调用子类中与父类保持继承关系的方法,不能调用子类新增的方法。
instancesof运算符
instancesof运算符用来判断一个对象是否指向某个类的实例,返回true或false
例如
if(pet instanceof Dog) {
Dog dog = (Dog) pet;
dog.catchingFlyDisc();
}
if(pet instanceof Bird) {
Bird bird = (Bird) pet;
bird.fly();
}
多态的应用
宠物店的例子
父类:宠物类
package com.kaifamiao.polymorphism;
public class Pet {
public void toHospital() {
System.out.println("宠物看病");
}
}
子类:狗类
package com.kaifamiao.polymorphism;
public class Dog extends Pet {
@Override
public void toHospital() {
System.out.println("狗狗看病");
}
public void catchingFlyDisc() {
System.out.println("接飞盘");
}
}
子类:鸟类
package com.kaifamiao.polymorphism;
public class Bird extends Pet {
@Override
public void toHospital() {
System.out.println("小鸟看病");
}
public void fly() {
System.out.println("飞翔");
}
}
定义宠物商店
package com.kaifamiao.polymorphism;
import java.util.Scanner;
public class PetShop {
/**
* 多态的应用之一:父类引用作为方法参数使用
* 当父类引用作为方法参数时,可以传入任何一个该类的子类对象
*/
public static void test(Pet pet) {
pet.toHospital();
if(pet instanceof Dog) {
((Dog)pet).catchingFlyDisc();
}
if(pet instanceof Bird) {
((Bird)pet).fly();
}
}
/**
* 多态的应用之二:父类引用作为方法的返回值
* 当父类引用作为方法返回值时,可以返回任意一个该了的子类对象
* @return
*/
public static Pet getPet() {
Pet pet = null;
Scanner s =new Scanner(System.in);
System.out.println("请输入要购买的宠物类别,1:狗,2:鸟");
int choice = s.nextInt();
switch(choice) {
case 1:
pet = new Dog();
break;
case 2:
pet = new Bird();
break;
default:
System.out.println("输入错误,程序终止");
}
return pet;
}
public static void main(String[] args) {
Pet pet = getPet();
PetShop.test(pet);
}
}
10.7.1父类作为方法参数
public static void test(Pet pet) {
}
多态的应用之一:父类引用作为方法参数使用 当父类引用作为方法参数时,可以传入任何一个该类的子类对象
10.7.2父类作为方法返回值
public static Pet getPet() {
}
多态的应用之二:父类引用作为方法的返回值 当父类引用作为方法返回值时,可以返回任意一个该类的子类对象