多态——Java的学习

一、多态的核心思想

  • “同一接口,不同实现”:父类引用可以指向子类对象,调用相同方法时根据实际对象类型执行不同的逻辑。

  • 分类

    • 编译时多态(静态多态):方法重载(Overload)。

    • 运行时多态(动态多态):方法重写(Override) + 向上转型(Upcasting)。

二、编译时多态:方法重载(Overload)

规则

  • 在同一个类中定义多个同名方法。

  • 参数列表必须不同(类型、顺序、数量)。

  • 与返回值类型无关。

public class Calculator {
    // 方法1:两个int相加
    public int add(int a, int b) {
        return a + b;
    }

    // 方法2:三个int相加(参数数量不同)
    public int add(int a, int b, int c) {
        return a + b + c;
    }

    // 方法3:两个double相加(参数类型不同)
    public double add(double a, double b) {
        return a + b;
    }
}

// 使用:
Calculator calc = new Calculator();
calc.add(2, 3);       // 调用方法1
calc.add(1.5, 2.5);   // 调用方法3

三、运行时多态:方法重写(Override)+ 向上转型

1. 方法重写(Override)

规则

  • 子类重写父类的方法,方法名、参数列表、返回值类型必须完全相同。

  • 子类方法的访问权限不能比父类更严格(例如父类方法是public,子类不能改为private)。

// 父类
class Animal {
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

// 子类1
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks: Woof!");
    }
}

// 子类2
class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Cat meows: Meow!");
    }
}
2. 向上转型(Upcasting)
  • 父类引用指向子类对象:Animal myPet = new Dog();

  • 通过父类引用调用被重写的方法时,实际执行的是子类的方法。

public class Main {
    public static void main(String[] args) {
        Animal animal1 = new Dog();  // 向上转型
        Animal animal2 = new Cat();

        animal1.makeSound();  // 输出 "Dog barks: Woof!"
        animal2.makeSound();  // 输出 "Cat meows: Meow!"
    }
}

四、多态的高级应用

1. 抽象类与多态
  • 抽象类可以定义抽象方法(无实现),强制子类重写。

  • 抽象类不能实例化,但可以通过多态指向子类对象。

    abstract class Shape {
        public abstract double calculateArea();  // 抽象方法
    }
    
    class Circle extends Shape {
        private double radius;
    
        public Circle(double radius) {
            this.radius = radius;
        }
    
        @Override
        public double calculateArea() {
            return Math.PI * radius * radius;
        }
    }
    
    class Square extends Shape {
        private double side;
    
        public Square(double side) {
            this.side = side;
        }
    
        @Override
        public double calculateArea() {
            return side * side;
        }
    }
    
    // 使用多态:
    Shape shape1 = new Circle(5);
    Shape shape2 = new Square(4);
    System.out.println(shape1.calculateArea());  // 输出圆的面积
    System.out.println(shape2.calculateArea());  // 输出正方形的面积
    2. 接口与多态
  • 接口定义行为规范,类通过implements实现接口。

  • 一个类可以实现多个接口,突破单继承限制。

interface Flyable {
    void fly();
}

interface Swimmable {
    void swim();
}

class Duck implements Flyable, Swimmable {
    @Override
    public void fly() {
        System.out.println("Duck flies with wings");
    }

    @Override
    public void swim() {
        System.out.println("Duck swims in water");
    }
}

// 使用接口多态:
Flyable flyingThing = new Duck();
flyingThing.fly();  // 调用Duck的fly方法

五、常见问题解答

  1. 为什么父类引用不能调用子类特有方法?
    父类引用只能访问父类中定义的方法和属性,若需调用子类特有方法,需向下转型。

  2. 多态与方法重载的区别?
    重载是编译时多态(静态),重写是运行时多态(动态)。

  3. 接口和抽象类如何选择?

    • 接口:定义行为规范,支持多继承。

    • 抽象类:提供部分实现,用于“is-a”关系。

六、练习建议

  1. 实现一个Animal父类,派生BirdFish子类,重写move()方法。

  2. 使用接口定义Playable,让不同类实现play()方法。

  3. 尝试通过多态实现一个简单的集合遍历(如List存储不同子类对象)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值