多态与抽象
多态是面向对象的核心特性,让代码更灵活、更易扩展。
什么是多态
多态是指同一个方法在不同对象上有不同的行为。
多态的好处
| 好处 | 说明 |
|---|---|
| 灵活性 | 同一接口,不同实现 |
| 可扩展性 | 新增子类不需要修改父类代码 |
| 简化代码 | 用父类引用操作子类对象 |
向上转型
子类对象可以赋值给父类引用。
JAVA
Animal animal = new Dog(); // 向上转型
示例:向上转型
JAVA
public class Animal {
public void eat() {
System.out.println("动物在吃东西");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗在啃骨头");
}
public void bark() {
System.out.println("汪汪叫");
}
}
public class PolymorphismDemo {
public static void main(String[] args) {
Animal animal = new Dog(); // 向上转型
animal.eat(); // 狗在啃骨头(调用的是Dog的eat)
// animal.bark(); // 编译错误!父类引用只能访问父类的方法
}
}
动态绑定
运行时根据实际对象类型调用方法,不是编译时类型。
示例:动态绑定
JAVA
public class Animal {
public void speak() {
System.out.println("动物发出声音");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println("汪汪汪");
}
}
public class Cat extends Animal {
@Override
public void speak() {
System.out.println("喵喵喵");
}
}
public class DynamicBinding {
public static void makeSound(Animal animal) {
animal.speak(); // 运行时决定调用哪个speak
}
public static void main(String[] args) {
makeSound(new Dog()); // 汪汪汪
makeSound(new Cat()); // 喵喵喵
}
}
抽象类
抽象类不能被实例化,只能被继承。
抽象方法
没有方法体的方法,子类必须实现。
JAVA
public abstract class Shape {
// 抽象方法:没有方法体
public abstract double area();
// 普通方法:有方法体
public void display() {
System.out.println("面积:" + area());
}
}
示例:抽象类
JAVA
public abstract class Shape {
protected String name;
public Shape(String name) {
this.name = name;
}
// 抽象方法
public abstract double area();
public abstract double perimeter();
public void display() {
System.out.println(name + " - 面积:" + area() + ",周长:" + perimeter());
}
}
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
super("圆形");
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
@Override
public double perimeter() {
return 2 * Math.PI * radius;
}
}
public class Rectangle extends Shape {
private double width, height;
public Rectangle(double width, double height) {
super("矩形");
this.width = width;
this.height = height;
}
@Override
public double area() {
return width * height;
}
@Override
public double perimeter() {
return 2 * (width + height);
}
}
public class ShapeDemo {
public static void main(String[] args) {
Shape circle = new Circle(5);
Shape rect = new Rectangle(4, 6);
circle.display(); // 圆形 - 面积:78.54,周长:31.42
rect.display(); // 矩形 - 面积:24.0,周长:20.0
}
}
接口
接口定义了一组规范,实现类必须遵守。
接口定义
JAVA
public interface 接口名 {
// 常量(默认public static final)
int MAX_SIZE = 100;
// 抽象方法(默认public abstract)
void method1();
int method2(int a);
}
接口实现
JAVA
public class 实现类 implements 接口名 {
@Override
public void method1() {
// 实现
}
@Override
public int method2(int a) {
return a;
}
}
示例:接口
JAVA
public interface Flyable {
void fly();
}
public interface Swimmable {
void swim();
}
public class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("鸭子在飞");
}
@Override
public void swim() {
System.out.println("鸭子在游泳");
}
}
public class InterfaceDemo {
public static void main(String[] args) {
Duck duck = new Duck();
duck.fly(); // 鸭子在飞
duck.swim(); // 鸭子在游泳
// 接口引用
Flyable flyer = new Duck();
flyer.fly();
}
}
接口 vs 抽象类
| 特性 | 接口 | 抽象类 |
|---|---|---|
| 关键字 | interface |
abstract class |
| 实现 | implements |
extends |
| 多实现 | 支持 | 不支持 |
| 构造方法 | 无 | 有 |
| 成员变量 | 只能常量 | 可以有普通变量 |
| 方法 | 抽象方法(Java 8前) | 可以有普通方法 |
面向接口编程
JAVA
public interface Payment {
void pay(double amount);
}
public class Alipay implements Payment {
@Override
public void pay(double amount) {
System.out.println("支付宝支付:" + amount);
}
}
public class WechatPay implements Payment {
@Override
public void pay(double amount) {
System.out.println("微信支付:" + amount);
}
}
public class PaymentDemo {
// 面向接口编程
public static void checkout(Payment payment, double amount) {
payment.pay(amount);
}
public static void main(String[] args) {
checkout(new Alipay(), 100); // 支付宝支付:100.0
checkout(new WechatPay(), 200); // 微信支付:200.0
}
}
❓ 常见问题
Q 什么时候用抽象类,什么时候用接口?
A 有共同状态和行为用抽象类,只定义规范用接口。
Q 接口可以有方法体吗?
A Java 8之后可以,用default关键字定义默认方法。
Q 向上转型后能调用子类特有方法吗?
A 不能,需要向下转型(强制转换)。
📖 小节
- 多态:同一方法在不同对象上有不同行为
- 向上转型:子类对象赋值给父类引用
- 动态绑定:运行时根据实际对象类型调用方法
- 抽象类:不能实例化,可以有抽象方法和普通方法
- 接口:定义规范,实现类必须遵守
📝 作业
- 动物体系: 定义Animal抽象类,Dog、Cat子类,实现多态调用
- 图形计算: 定义Shape接口,实现Circle、Rectangle,计算面积
- 支付系统: 定义Payment接口,实现多种支付方式
下一课
下一课我们将学习 接口进阶与Lambda,了解接口的高级特性和Lambda表达式。



