java学习-多态抽象类接口
Posted zcb_bai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java学习-多态抽象类接口相关的知识,希望对你有一定的参考价值。
一、多态
1.1 多态的概述
- 多态是面向对象一大特征
- 多态 : 表示事物的多种形态(事物的多种表现形式)
- 多态发生的前提:
1) 需要具有子父类的继承关系(类与接口实现关系)
2) 子类重写从父类继承来的方法
3) 父类的引用指向子类的对象
举例 :
class Person{}
class Doctor extends Person{}
class Teacher extends Person{}
多态表达式:
Person p; // 父类引用
new Doctor(); // 子类对象
new Teacher() ;// 子类对象
Person p = new Doctor(); // 人类p的表现形式是医生
Person p1 = new Teacher(); // 人类p1的表现形式是教师
以上表达式能体现出人类的多种表现形式,这就是多态的概念
代码
public class Person { public void eat() { System.out.println("人都需要吃饭"); } }
public class Doctor extends Person { @Override public void eat() { System.out.println("医生吃的比较清淡"); } }
public class Teacher extends Person { @Override public void eat() { System.out.println("教师今天想吃凉皮"); } }
public class TestDuoTai { public static void main(String[] args) { // 多态表达式 Person p = new Doctor(); p.eat();// 医生吃的比较清淡 Person p1 = new Teacher(); p1.eat();// 教师今天想吃凉皮 } }
1.12多态中成员方法的特点
- 编译看左,运行看右
使用多态表达式调用成员方法
1) 编译看左 : 编译代码时, 如果多态表达式调用的这个方法, 在 等号的左边的类型中不存在(没定义), 那么直接报错,无法编译通过. 如果等号左边的类型中存在调用的方法,编译成功
2) 运行看右 : 使用多态的表达式调用方法,运行时动态绑定等号右边的类型中的方法实现, 实际运行的就是等号右边子类中的重写方法
代码
public class Person { public void eat() { System.out.println("人都需要吃饭"); } }
public class Doctor extends Person { @Override public void eat() { System.out.println("医生吃的比较清淡"); } // 医生特有的救人功能 public void savePerson() { System.out.println("医生可以治病救人"); } }
public class Teacher extends Person { @Override public void eat() { System.out.println("教师今天想吃凉皮"); } // 老师特有功能授课 public void teach() { System.out.println("老师可以授课"); } }
public class TestDuoTai { public static void main(String[] args) { // 多态表达式 // 1. 编译看左,运行看右 Person p = new Doctor(); // eat方法在等号左边的类型Person中存在(定义) p.eat();//医生吃的比较清淡 // savePerson方法在等号左边的类型Person中不存在,因此报出编译错误 // p.savePerson(); //The method savePerson() is undefined for the type Person Person p1 = new Teacher(); p1.eat();//教师今天想吃凉皮 // p1.teach(); } }
1.3多态的向上和向下转型
- 多态向上转型 : 父类的引用指向子类对象(多态表达式)
Person p = new Doctor();
向上转型的实质 : 对象引用p使用范围缩小, 只能使用子父类中的共有方法
2.多态向下转型 :
目的 : 为了解决多态表达式中,无法使用子类特有方法的局限性, 想要使用子类中的特有方法功能
多态向下转型公式: 将指向子类对象的父类引用, 恢复成子类类型
举例 : Doctor d = (Doctor)p;
向下转型实质 : 对象引用p使用范围变大, 可以使用子类中的内容
1.4 多态的好处
- 多态好处 : 提高代码的扩展性
- 方法的参数列表上 : 定义一个方法功能, 形式参数可以是父类数据类型, 在方法中可以使用父类参数中的任意功能; 当调用这个方法时, 实际参数可以是当前父类类型对象本身,也可以是这个父类的任意一个子类类型对象
- 一个类型不一定非通过new对象才能创建, 很多情况下, 方法功能返回值类型就是引用数据类型, 需要一个对应的引用类型接方法返回值, 若这个引用的具体类型不清楚,可以直接使用一个父类类型作为这个方法的返回值类型承接
需求 : 现有一农场,需要设计出一个方法, 功能是提供不同的动物类型,能输出每一种动物需要投喂的食物, 请根据多态设计出这个方法功能
举例 : 给该方法传递猫类型数据 : 提示, 喂鱼 ; 给该方法传递狗类型数据 : 提示 , 吃骨头; 给该方法传递羊类型数据 : 提示 , 喂草 .... 每一种动物都能得到对应的喂食结果
代码
public class Animal { // 将所有动物都需要喂食功能 : eat public void eat() { System.out.println("所有动物都需要喂食"); } }
public class Cat extends Animal { @Override public void eat() { System.out.println("猫喂鱼"); } }
public class Dog extends Animal { @Override public void eat() { System.out.println("狗喂骨头"); } }
public class Farmer { // 方法功能 : 将每一种动物喂食结果显示出来 public void wei(Animal a) {// Animal a = new Sheep(); a.eat(); } public void useI(int i) {// int i = 10; System.out.println(i); } }
二、 抽象类
2.1 抽象方法和抽象类
- 抽象 : 表示无法使用语言进行描述, 无法实现的, 虚无缥缈,没有具体存在
将事物的共性向上抽取,抽取到父类中, 但是当共性抽取到一定程度时, 父类中不知道如何实现共性内容才能让每一个子类都满足实际需求, 于是父类中将共性方法只做方法的声明,而没有方法的实现,这样的方法称为抽象方法
2.抽象方法的定义:
需要使用关键字 : abstract
修饰符 abstract 返回值类型 方法名(参数列表);
3.抽象类的定义:
修饰符 abstract class 类名{
// 抽象方法只能存在于抽象类中
}
4.抽象方法存在是为了为子类限定一些需要实现的规则
代码
public abstract class Animal { // 抽象方法 // The abstract method eat in type Animal can only be defined by an abstract class // 抽象方法只能定义在抽象类中 public abstract void eat(); }
2.2 抽象的特点
- 抽象类和抽象方法都需要使用 abstract 抽象关键字
public abstract class Animal{
public abstract void eat();
}
2.抽象类和抽象方法之间的关系:
1) 抽象方法必须定义在抽象类中
2) 抽象类中可以没有抽象方法
3.抽象类的实例化(实例化 : new对象)
1) 抽象类不能实例化对象(不能new对象)
因为抽象类中可以含有抽象方法, 而抽象方法因为没有方法体,不能运行的,因此抽象类不能new对象
2) 抽象类等着当父类,等着被子类继承, 需要一个子类继承这个抽象类, 让子类将抽象父类中的所有抽象方法全部重写, 通过创建子类对象,实现方法的调用
4.抽象类的子类前途:
1) 子类将抽象父类中的所有抽象方法全部重写, 子类可以正常创建对象使用
2) 子类没有将抽象父类中的所有抽象方法全部重写, 子类仍然还是一个抽象类
2.3抽象类中的成员
抽象类中的成员 : 先把抽象类当做一个普通类, 在此基础上可以定义抽象方法
1.可以定义成员变量
2.可以定义构造方法
一个类型是否可以定义构造方法,与这个类型能否创建对象无关, 与类型中是否能定义成员变量有关. 只要一个类型中可以定义成员变量,那么这个类型就可以定义构造方法
3.可以定义非抽象方法
为了给子类直接继承使用
4.可以定义抽象方法
为了给子类限定需要实现的规则
抽象的练习 :
每个员工Employee都具有属性(姓名,工号,工资),行为 : 工作
程序员类: 属性(姓名,工号,工资,奖金), 行为 : 工作(软件开发)
测试工程师类 : 属性(姓名,工号,工资), 行为 : 工作(软件测试)
项目经理类 : 属性(姓名,工号,工资,奖金),行为 : 工作(控制工作进度)
请设计出合适的类关系,并测试
代码
public abstract class Employee { // 姓名,工号,工资 private String name; String id; double salary; public String getName() { return name; } public void setName(String name) { this.name = name; } public abstract void work(); }
public class Employee_程序开发 extends Employee{ private double jiangjin; public Employee_程序开发(String name , String id, double salary, double jiangjin) { super(); this.jiangjin = jiangjin; this.id = id; setName(name); this.salary = salary; } public Employee_程序开发() { super(); } public double getJiangjin() { return jiangjin; } public void setJiangjin(double jiangjin) { this.jiangjin = jiangjin; } @Override public void work() { System.out.println(getName() +"---"+ id +"---"+ salary + "---"+jiangjin+"程序员做开发"); } }
public class Employee_测试工程师 extends Employee{ @Override public void work() { System.out.println("测试工作"); } }
public class TestEmployee { public static void main(String[] args) { Employee_程序开发 e1 = new Employee_程序开发("小张","007",15678.99,3200); e1.work(); Employee_测试工程师 e2 = new Employee_测试工程师(); e2.work(); } }
三、接口
3.1 接口的概述
- 接口 : 一系列规则的集合, 接口中都是抽象方法
- 接口好处:
因为接口中全部都是抽象方法, 抽象方法只方法的声明, 方法功能的声明和方法的实现分离, 让类型与类型之间的耦合度(关联度)降低
3.2 接口的定义
- 接口的定义 :
使用关键字 interface : 用于定义出接口类型
修饰符 interface 接口名{
// 抽象方法(随着JDK版本的推进, 接口中不仅仅只有抽象方法,目前学习中,以抽象方法为学习重点,JDK8新特性,讲解接口中的其他方法定义)
}
代码
public interface MyInter { // 定义抽象方法 public abstract void fun(); public abstract boolean equalDouble(double d, double d1); }
3.3 接口的特点
- 接口中的方法都是抽象方法
- 接口不能实例化对象(不能new对象)
接口需要一个实现类, 将接口中的所有抽象方法重写,通过创建实现类对象,调用重写方法
3.类与接口之间的关系:实现关系 implements (与类和类之间的继承extends关系非常相似)
举例 : interface MyInter{}
class MyInterImpl implements MyInter{
// 将接口中的抽象方法全部重写;
}
4.接口实现类的前途:
1) 如果实现类将接口中的所有抽象方法全部重写,那么这个实现类可以正常使用
2) 如果实现类没有将接口中的所有抽象方法全部重写, 那么这个实现类是抽象类, 抽象类不能实例化对象
3.4接口中的成员
- 成员常量 : 接口中的所有成员变量都是常量, 因为接口中的成员变量有默认修饰, public static final, 写出修饰或者不写,以及写出修饰符的一部分, 默认修饰不变
- 接口中无法定义构造方法: 因为接口中没有成员变量
- 抽象方法 : 有默认修饰符, public abstract
以上是关于java学习-多态抽象类接口的主要内容,如果未能解决你的问题,请参考以下文章