抽象类
为什么要用抽象类
- 在面向对象的概念中,所有的对象都是通过类来表述,但并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一类具体的对象,这样的类就是抽象类。
- 抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。
抽象类的使用
- abstract放在class前,指明该类是抽象类
- abstract放在方法声明中,则该方法是抽象方法,抽象方法没有方法体
- 一个抽象类可以含有多个抽象方法,也可以含有已实现的方法
- 抽象方法必须在子类中被实现,除非子类是抽象类
示例:
形状抽象类
public abstract class Shape {
double dim;
public Shape(double dim) {
this.dim = dim;
}
// 抽象方法,获得面积
public abstract double callArea();
// 抽象方法,获得周长
public abstract double callPerimeter();
}
定义Shape类的一个子类Circle:
public class Circle extends Shape {
public Circle(double dim) {
super(dim);
}
// 实现抽象方法callArea()
public double callArea() {
// 返回圆的面积
return 3.14 * dim * dim;
}
// 实现抽象方法callPerimeter()
public double callPerimeter() {
// 返回圆的周长
return 2 * 3.14 * dim;
}
}
main方法测试:
public static void main(String[] args) {
// 声明一个Shape对象,指向实现它的子类对象
Shape shape = new Circle(10);
// 调用callArea()求圆的面积,并输出
System.out.println("圆的面积是:" + shape.callArea() );
// 调用callPerimeter()求圆的周长,并输出
System.out.println("圆的周长是:" + shape.callPerimeter() );
}
结果:
圆的面积是:314.0
圆的周长是:62.800000000000004
注意:
- 抽象类不能实例化,但可以指向一个实现它的子类对象;
- abstract不能与final同时修饰一个类;
- abstract不能和static、private、final或native并列
final关键字
- final关键字表示的不可变的。一个类不希望被其它类继承,可以使用final,Java中的String类就是一个final类。
- 方法不希望被重写,可以使用final,final修饰的方法表示此方法已经是“最后的、最终的”含义,即父类的final方法是不能被子类所覆盖的,也就是说子类是不能够存在和父类一模一样的方法的。
多态
概念:
多态是指,同一个事件发生在不同的对象上会产生不同的结果。
实现
-
编写父类
-
编写子类,子类重写父类方法
-
运行时,使用父类的类型、子类的对象
如:Pet pet = new Dog();
多台实现的两种方式:
1.使用父类作为方法形参实现多态
实现:
public abstract class Pet { //Pet类作为抽象类
public abstract void eat();
}
public class Dog extends Pet { // 狗狗类为子类,实现Pet类的方法
public void eat() {
System.out.println("狗狗吃饭中!");
}
}
public class Penguin extends Pet { // 企鹅类为子类,实现eat()方法
public void eat() {
System.out.println("企鹅吃饭中!");
}
}
public class Master { //主人类,负责给宠物投食,将抽象类Pet作为方法形参
public void feed(Pet pet) {
pet.eat();
}
}
public class Test { // 测试类,给宠物喂食
public static void main(String[] args) {
Dog dog = new Dog();
Penguin pgn = new Penguin();
Master master=new Master();
master.feed(dog);//主人给狗狗喂食
master.feed(pgn);//主人给企鹅喂食
}
}
运行结果:
狗狗吃饭中!
企鹅吃饭中!
2.使用父类作为方法返回值实现多态
实现:
public Pet getPet(int typeId){ // 主人领养宠物
Pet pet=null;
if(typeId==1){
pet= new Dog();
}else if(typeId==2){
pet = new Penguin();
}
return pet;
}
public class Test2 { // 测试类 根据控制台选择,领养宠物
public static void main(String[] args) {
System.out.println("欢迎您来到宠物店!");
System.out.print("请选择要领养的宠物类型:(1、狗狗 2、企鹅)");
Scanner input = new Scanner(System.in);
//获取选择的宠物类型
int typeId=input.nextInt();
//领养宠物
Master master=new Master();
Pet pet=master.getPet(typeId);
if(pet!=null){
System.out.println("领养成功!");
//开始喂食
master.feed(pet);
}else{
System.out.println("对不起,没有此类型的宠物,领养失败");
}
}
}
结果:
接口
特点:
- Java是单继承的语言,利用接口可以模拟多继承;
- 接口是对抽象类的进一步抽象,是方法声明和常量的定义集合;
- 接口是一种行为规范,是一种“契约”;
- 接口不可以被实例化
- 实现类必须实现接口的所有方法
- 实现类可以实现多个接口
- 接口中的变量都是静态常量
编码实操
interface USB { // USB接口
void read();
void write();
}
// U盘类
class UDisk implements USB {
public void read() {
System.out.println("U盘正在通过USB功能读取数据");
}
public void write() {
System.out.println("U盘正在通过USB功能写入数据");
}
}
//键盘类
class Keyboard implements USB {
public void read() {
System.out.println("键盘正在通过USB功能读取数据");
}
public void write() {
System.out.println("键盘正在通过USB功能写入数据");
}
}
// 测试类
public class Main {
public static void main(String[] args) {
UDisk udisk = new UDisk(); //生成一个实现可USB接口(标准)的U盘对象
udisk.read(); //调用U盘的read( )方法读取数据
udisk.write(); //调用U盘的write( )方法写入数据
Keyboard keyboard = new Keyboard(); //生成一个实现可USB接口(标准)的键盘对象
keyboard.read(); //调用键盘的read( )方法读取数据
keyboard.write(); //调用键盘的write( )方法写入数据
}
}
结果:
U盘正在通过USB功能读取数据
U盘正在通过USB功能写入数据
键盘正在通过USB功能读取数据
键盘正在通过USB功能写入数据