多态
概念:父类类型引用指向子类对象(多态的第一种形式)
多态的前提是继承
语法:
父类类名 对象名 = new 子类类名();
1.多态的类型转换:
1.1自上类型转换
子类型转成父类型(dog–>pet)
作用:
增强类的选择范围,降低类的能力(只能访问父类中定义的内容)
1.2自下类型转换
语法:(子类型)父类型对象;(类似于强转)
作用:
降低类的选择范围,增强类的功能。(从pet转回dog,可以访问dog中的私有成员变量,前提是pet原本是由dog上转上来的)
2.instanceof关键字
含义:判断左边的对象是否是右边的类型。
语法:
if(pet instanceof dog){
Dog dog = (Dog)pet;
}else{
......
}
//instanceof属于boolean类型,如果是返回true,否则返回false。
3.访问特点
3.1 (属性)成员变量访问特点
不同名:
多态中访问不同名属性,编译看表达式的左边
同名:
多态中访问不同名属性,编译时看表达式的左边。
多态中访问同名属性,运行时看表达式左边。
3.2 成员方法访问特点
不同名:
多态中访问不同名方法,编译时看表达式左边
同名:
多态中同名方法,运行时看表达式右边(重写后的)
多态中同名静态方法,运行时看表达式左边(静态方法不能继承,所以这两个是完全无关的方法)
练习
程序员:属性(姓名、工号、工资),方法(敲代码)。
项目经理:属性(姓名、工号、工资、奖金),方法(项目控制)。
老板:属性(姓名、工号),方法(号令多个员工同时工作)。
class Employee{//雇员
private String name;
private String id;
private double wage;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public double getWage() {
return wage;
}
public void setWage(double wage) {
this.wage = wage;
}
public void mothed(){//工作
}
}
class Program extends Employee {//程序员
@Override
public void mothed(){
System.out.println("敲代码");
}
}
class Manager extends Employee {
private int bonus;
public int getBonus() {
return bonus;
}
public void setBonus(int bonus) {
this.bonus = bonus;
}
@Override
public void mothed(){
System.out.println("项目控制");
}
}
class Boss{
private String name;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void order(Employee... empls){//动态参数技术
for (int i = 0; i < empls.length; i++) {
empls[i].mothed();
}
}
}
public class Demo {
public static void main(String[] args) {
Program pro = new Program();
Manager ma = new Manager();
Boss boss = new Boss();
boss.order(pro,ma);
}
}
抽象类
1.抽象类
使用时机:
1.该类中存在抽象方法
2.该类的对象只是一种概念,在现实生活中不存在该类的对象
语法:
abstract class 类名{...}
注意点:
- 抽象类中不一定具有抽象方法,抽象类中还可以有其他成员
- 有抽象方法的一定是抽象类
- 抽象类无法实例化
- 抽象类的目的是被子类继承
- 抽象类具有构造方法(子类继承父类在调用构造方法时会先调用父类的构造方法,而抽象类就是需要被继承的,所以抽象类具有构造方法)
- abstract不能与private一起使用,因为abstract修饰方法被子类重写,private修饰的方法只能本类使用,出现矛盾。
- abstract不能与final一起使用,因为abstract修饰类能被子类继承,final修饰的类不被子类继承。abstract修饰方法能被子类重写,final修饰的方法不被子类重写。所以出现矛盾。
2.抽象方法
使用时机:例如宠物类的eat()方法,该方法无法准确描述该类对象的具体行为(吃什么无法得知)
语法:
abstract 返回值类型 方法名(参数列表);
注意点:
- 抽象方法没有方法体
- 抽象方法目的就是被子类重写
- 父类有抽象方法,子类必须重写父类全部的抽象方法,除非子类自己也是一个抽象类
- 有抽象方法的一定是抽象类
接口
语法:
interface 接口名{
接口成员(静态常量,抽象方法)
}
注意:
- 接口中静态常量中的final和static可以不写
- 接口中抽象方法中的abstract可以不写
- 接口中所有成员的public修饰符都可以省略。但真实开发中不会省略,原因是方便被重写
类与接口之间的关系
1.接口可以被类实现
语法:
访问修饰符 class 类名 [extends 父类] implements 接口名1,接口名2,......{
成员
}
在implements后可以实现多个接口,每个接口以","隔开,简称多实现。(为了打破类的单继承)
2.接口可以被接口继承
语法:
访问修饰符 interdace 接口名 extends 父接口1,父接口2,......{
成员
}
成员:接口特有的静态常量及特有抽象方法
作用:
扩展类的功能
多态的第二种形式:接口类型引用指向实现类对象
3.接口与抽象类区别
- 定义不同:接口使用interface修饰,抽象类使用abstract class修饰
- 成员不同:接口只能有静态常量和抽象方法,抽象类可以有抽象方法也可以有普通成员
- 构造方法不同:接口没有构造方法,抽象类有构造方法。
- 使用方式不同:接口多继承和多现实,抽象类单继承
- 继承关系上不同:接口被接口继承,抽象类被类继承。