面向对象三大特征(多态)

本文详细介绍了Java中的多态概念,包括多态的实现条件(子类继承父类并重写方法)、变量和方法调用的特点、向上和向下转型,以及编译时和运行时多态的区别。此外,还探讨了多态带来的扩展性和使用场景,如对象数组和方法参数传递。
摘要由CSDN通过智能技术生成

多态

同类型的对象表现出的不同形态

多态的表现形式

父类类型 对象名称 = 子类对象

多态实现的条件

  • 子类继承父类,并且子类重写父类方法

  • 父类引用指向子类对象。(父类引用可以指向任意一个子类的对象)

  • 方法重写是基础

  • 父类引用调用方法时,实际上调用的是子类的方法(父类指向哪个子类就调用的哪个子类的方法),不同的子类有不同的方法实现,体现出同一个方法在不同子类中的不同形态的表现。

多态调用成员的特点

  • 变量调用:编译看左边,运行也看左边

  • Animal dog = new Dog();这个语句的左边或者右边

    javac编译代码的时候,会看左边有没有这个变量,如果有编译成功,如果没有编译失败。

    运行的时候,会获取左边父类的成员变量的值

public class Animal {
    String name = "动物";

    public void show() {
        System.out.println("Animal");

    }
}



public class Dog extends Animal{
    String name = "狗";

    @Override
    public void show() {
        System.out.println("狗方法");

    }
}
public class Cat extends Animal{
    String name = "猫";

    @Override
    public void show() {
        System.out.println("猫方法");

    }
}
public class AnimalTest {
    public static void main(String[] args) {
        //创建对象
        Animal dog =  new Dog();
        System.out.println(dog.name);
        Animal cat = new Cat();
        System.out.println(cat.name);


    }
}

运行结果是:

动物
动物
  • 方法调用:编译看右边,运行看右边

  • javac编译代码的时候,会看左边有没有这个变量,如果有编译成功,如果没有编译失败。

    运行的时候,会获取右边子类的成员变量的值

子类、父类同上

public class AnimalTest {
    public static void main(String[] args) {
        //创建对象
        Animal dog =  new Dog();
        dog.show();
        Animal cat = new Cat();
        cat.show();
    }
}

运行结果

狗方法
猫方法

多态的好处

使用父类作为参数,就可以接受所有子类对象,体现多态的扩展性与便利

对象数组的使用

在Java中,我们可以创建包含对象的数组。对象数组是一种特殊类型的数组,其中每个元素都是一个对象的引用。你可以将任何类的对象存储在对象数组中,并通过索引来访问和操作这些对象。

使用格式:

// 创建对象数组
ClassName[] arrayName = new ClassName[size];

// 实例化对象并存储到数组中
arrayName[index] = new ClassName();

// 访问对象数组中的元素
ClassName obj = arrayName[index];

// 修改对象数组中的元素
arrayName[index].propertyName = value;

例:

class Person {
    String name;
    int age;
}

public class Main {
    public static void main(String[] args) {
        // 创建对象数组
        Person[] people = new Person[3];

        // 实例化对象并存储到数组中
        people[0] = new Person();
        people[0].name = "Alice";
        people[0].age = 25;

        people[1] = new Person();
        people[1].name = "Bob";
        people[1].age = 30;

        people[2] = new Person();
        people[2].name = "Charlie";
        people[2].age = 35;

        // 访问对象数组中的元素
        System.out.println("Name: " + people[0].name + ", Age: " + people[0].age);
        System.out.println("Name: " + people[1].name + ", Age: " + people[1].age);
        System.out.println("Name: " + people[2].name + ", Age: " + people[2].age);
    }
}

使用对象作为方法的参数

在Java中,我们可以将对象作为方法的参数传递。这对于需要传递多个相关数据的情况非常有用。通过将对象作为参数传递给方法,我们可以方便地访问和操作该对象的属性。

class Person {
    String name;
    int age;
}

public class Main {
    public static void printPersonInfo(Person person) {
        System.out.println("Name: " + person.name + ", Age: " + person.age);
    }

    public static void main(String[] args) {
        Person person = new Person();
        person.name = "Alice";
        person.age = 25;

        // 调用方法,并传递对象作为参数
        printPersonInfo(person);
    }
}

instanceof 的使用

instanceof 是 Java 中的关键字,用于判断一个对象是否是某个类的实例或子类的实例。它可以用来做类型检查和类型转换。

示例代码:

Animal cat = new Cat();

if (cat instanceof Cat) {
    System.out.println("cat is an instance of Cat");
}

if (cat instanceof Animal) {
    System.out.println("cat is an instance of Animal");
}

向上转型

子类向父类转换 称为向上转型。它是一种隐式的类型转换,在继承关系存在的情况下可以自动进行。

格式:

父类类型 引用变量 = new 子类类型();

调用实例方法是,要看是哪个对象调用的就执行哪个方法,调用 static 方法时,调用的是父类方法(静态方法属于类)实例方法看等号右边,静态方法看等号左边

例:

Pet pet = new Dog();
pet.toHospital();

pet 向上转型成Dog

  • 只能调用父类声明的方法,子类扩展的方法不能调用

  • 调用实例方法时,看是那个对象调用就执行哪个对象的方法

向下转型

如果想调用子类新增的方法,可以通过把父类转换成子类实现,称为向下转型,必须通过强制转型实现

格式:

子类类型  引用变量类型 = (子类类型) 父类类型的引用变量;

在进行向下转型之前,应先使用instanceof运算符进行类型检查,以确保转型是安全的。

  • 使用 instanceof 时,对象的类型必须和 instanceof 后面的参数所指定的类有继承关系,否则会出现编译错误。

  • 在 java16 的增强之后,对于 instanceof 的判断以及类型转换可以合二为一,如下:

if (pet instanceof Dog dog) {
	dog.catchingFlyDisc();
}
if (pet instanceof Brid bird) {
	brid.fly();
}

向下转型实例:

Animal animal = new Cat(); // 向上转型
Cat cat;

if (animal instanceof Cat) { // 类型检查
    cat = (Cat) animal; // 向下转型
    // 访问和操作Cat类特有的属性和方法
}

编译时多态(重载)

在编译阶段根据方法的参数类型和数量来决定调用哪个方法。多个同名方法通过参数列表来区分。例如,重载的print()方法可以接受不同类型的参数,并根据参数类型的不同执行不同的代码逻辑。

class Printer {
    public void print(String str) {
        System.out.println("Printing string: " + str);
    }

    public void print(int num) {
        System.out.println("Printing number: " + num);
    }
}

public class Main {
    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print("Hello");
        printer.print(123);
    }
}

运行时多态(重写)

在程序运行时根据对象的实际类型来决定调用哪个方法。子类可以重写(覆盖)父类的方法,并改变其行为。通过使用父类类型的引用来引用子类类型的对象,可以实现多态。

class Animal {
    public void makeSound() {
        System.out.println("Animal is making a sound");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Cat is meowing");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog is barking");
    }
}

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

        animal1.makeSound(); // 调用Cat类的makeSound方法
        animal2.makeSound(); // 调用Dog类的makeSound方法
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值