面向对象——多态

多态(Polymorphism)

概述

多态指同一个对象在不同情境下的多种表现形式。它分为对象的多态性和类型的多态性。

  1. 对象的多态性:同一个对象可以被不同类型的引用指向,从而在不同情境下以不同方式使用。这体现了一个对象能够通过不同的名称和描述来表现自己。

  2. 类型的多态性:同一类型的引用可以指向该类型的不同子类对象。在不同的情境下,可以使用同一个类型的引用来操作不同的对象实例。

    • 本质:在不同场景中,同一个方法调用可以有不同的实现。

多态的前提条件

  1. 继承/实现关系:必须存在类的继承或接口的实现关系。
  2. 方法重写:子类需要对父类的方法进行重写。
  3. 父类引用指向子类对象:通过使用父类类型的引用来指向子类的实例。

代码示例

public class Simple01 {
    public static void main(String[] args) {
        Animal a = new Cat(); // 父类引用指向子类对象
        a.speak(); // 调用的是 Cat 类的 speak 方法
    }
}

class Animal {
    public void speak() {
        System.out.println("动物发声");
    }
}

class Cat extends Animal {
    @Override
    public void speak() {    
        System.out.println("喵喵喵喵喵");
    }
}

多态中成员变量的访问特点

  1. 编译时和运行时都看引用类型(左边)。
  2. 编译时检查引用类型中是否有相应的成员变量,若有则编译成功,否则失败。
  3. 运行时访问的也是引用类型中的成员变量。

代码示例

public class Simple02 {
    public static void main(String[] args) {
        Animal a = new Cat();
        System.out.println(a.age); // 访问的是父类的 age
    }
}

class Animal {
    int age = 2;
}

class Cat extends Animal {
    int age = 3; // 不会被访问到
    String color = "black";
}

多态中成员方法的访问特点

  1. 编译看左边(引用类型),运行看右边(实际对象类型)。
  2. 编译时检查引用类型中是否有相应的方法声明,若有则编译成功,否则失败。
  3. 运行时调用实际对象所属类中重写的方法。

代码示例

public class Simple03 {
    public static void main(String[] args) {
        Animal3 a = new Cat3();
        a.speak(); // 调用的是 Cat3 类的 speak 方法
    }
}

class Animal3 {
    public void speak() {
        System.out.println("动物发声");
    }
}

class Cat3 extends Animal3 {
    @Override
    public void speak() {
        System.out.println("喵喵");
    }

    public void catchMouse() {
        System.out.println("抓老鼠");
    }
}

向上转型与向下转型

  1. 向上转型(Upcasting)

    • 子类对象赋值给父类引用。
    • 访问范围被限制为父类的定义。
  2. 向下转型(Downcasting)

    • 父类引用强制转换为子类引用。
    • 允许访问子类特有的成员。

代码示例

public class Simple05 {
    public static void main(String[] args) {
        Man m = new SuperMan(); // 向上转型
        m.dealBusiness(); // 调用的是 SuperMan 重写的方法

        SuperMan sm = (SuperMan) m; // 向下转型
        sm.fly(); // 访问子类的特有方法
    }
}

class Man {
    String name = "Jack";

    public void dealBusiness() {
        System.out.println("普通的谈生意");
    }
}

class SuperMan extends Man {
    String name = "James";

    @Override
    public void dealBusiness() {
        System.out.println("几个亿的大生意");
    }

    public void fly() {
        System.out.println("到处飞着救人");
    }
}

多态的好处

  1. 提高代码可扩展性:无需修改已有代码即可添加新功能。
  2. 灵活的参数传递:方法参数使用父类类型,可以接收任何子类实例。
  3. 广泛的对象来源:不仅限于实例化创建的对象,还可通过反射、文件读取等方式获取对象。

代码示例

public class Simple06 {
    public static void main(String[] args) {
        JuiceMachine jm = new JuiceMachine();
        jm.makeJuice(new Apple()); // 调用 Apple 的 flow 方法
    }
}

class JuiceMachine {
    public void makeJuice(Fruit f) {
        f.flow(); // 多态机制
    }
}

class Fruit {
    public void flow() {}
}

class Apple extends Fruit {
    @Override
    public void flow() {
        System.out.println("流出苹果汁");
    }
}

class Orange extends Fruit {
    @Override
    public void flow() {
        System.out.println("流出橙汁");
    }
}

抽象类(Abstract Class)

概述

  1. 定义:抽象类是包含抽象方法的类,无法直接实例化。
  2. 使用场景:用来捕获子类的通用特征和行为,实现代码复用。

抽象类的定义格式

abstract class 类名 {
    // 抽象方法和非抽象方法
}

代码示例

abstract class Animal {
    public abstract void eat();
}

class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

抽象方法

  1. 定义:没有方法体的声明方式,只提供方法名和参数,没有具体实现。
  2. 用法:子类必须实现所有抽象方法,否则子类也必须声明为抽象类。

代码示例

abstract class Animal2 {
    public abstract void eat(); // 抽象方法
}

class Dog2 extends Animal2 {
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
}

抽象类的特点

  1. 必须使用abstract关键字:用于标记类和方法。
  2. 抽象方法和抽象类关系:抽象方法必须在抽象类中,抽象类不一定要有抽象方法。
  3. 不能直接实例化:需要通过具体子类来创建对象。
  4. 子类可以是抽象类:如果子类没有实现所有抽象方法,子类仍然需要声明为抽象类。

抽象类成员的特点

  1. 成员变量:可以定义普通变量和常量,但不能是抽象变量。
  2. 构造方法:抽象类可以有构造方法,用于子类实例化时初始化操作。
  3. 成员方法:可以是抽象方法,也可以是具体方法,以提高代码复用。

代码示例

abstract class Fu {
    int i = 10;
    final int j = 20;

    public abstract void test();

    public Fu() {
        i = 100;
    }
}

class Zi extends Fu {
    @Override
    public void test() {
        System.out.println("Zi:" + i);
    }
}

接口(Interface)

概述

  1. 定义:接口是一组方法规范的集合,所有方法都必须由实现类实现。
  2. 作用:分离方法定义和实现,降低代码耦合性。

接口的特点

  1. 定义接口:使用interface关键字,接口中只能定义抽象方法。
  2. 实现接口:类使用implements关键字来实现接口中的方法。
  3. 接口不能实例化:必须通过实现类来创建对象。
  4. 接口的实现类可以是普通类或抽象类:如果是普通类,必须实现所有接口方法;如果是抽象类,可以不实现接口方法。

代码示例

interface MyInterA {
    void test1(); // 接口中的方法默认为 public abstract
}

class MyInterImplB implements MyInterA {
    @Override
    public void test1() {
        System.out.println("MyImplB");
    }
}

接口中成员的特点

  1. 成员变量

:只能定义常量,默认修饰符为public static final
2. 构造方法:接口中不能有构造方法。
3. 成员方法:默认修饰符为public abstract

接口中成员示例

interface MyInterface {
    int NUM = 10; // 常量,默认 public static final

    void test(); // 抽象方法,默认 public abstract
}

接口与抽象类的区别

  1. 设计理念:接口用于定义行为标准,抽象类用于提供基本功能。
  2. 成员特点
    • 抽象类可以有非抽象方法和成员变量。
    • 接口只能定义常量和抽象方法。

代码示例

abstract class Animal4 {
    public abstract void eat();
}

interface Flyable {
    void fly();
}

class Bird extends Animal4 implements Flyable {
    @Override
    public void eat() {
        System.out.println("鸟吃虫子");
    }

    @Override
    public void fly() {
        System.out.println("鸟在飞");
    }
}

内部类(Inner Class)

概述

内部类是定义在另一个类内部的类,可以分为成员内部类和局部内部类。

  1. 成员内部类:与成员变量定义在同一位置,属于类的成员。
  2. 局部内部类:定义在方法或代码块内部,只能在其作用域内使用。

代码示例

class Outer {
    private int num = 10;

    // 成员内部类
    class Inner {
        public void show() {
            System.out.println(num);
        }
    }

    // 局部内部类
    public void method() {
        class InnerLocal {
            public void display() {
                System.out.println(num);
            }
        }

        InnerLocal il = new InnerLocal();
        il.display();
    }
}

使用内部类的注意事项

  1. 访问外部类成员:内部类可以直接访问外部类的成员,甚至是私有成员。
  2. 创建内部类对象:需要通过外部类对象来创建内部类对象。

代码示例

public class Simple08 {
    public static void main(String[] args) {
        Outer.Inner oi = new Outer().new Inner();
        oi.show();
    }
}

这份文档旨在以更清晰和更结构化的方式来阐述多态、抽象类、接口和内部类的概念。

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值