对象的多态性

目录

一 、对象转型 

 1 、对象的向上转型

2 、对象的向下转型

注意:在进行对象向下转型前,必须先进行对象向上转型,否则将出现对象转换异常

二 、对象多态性的应用

设计一个方法,要求此方法可以接收父类的任意子类对象,并调用方法

1 、不使用对象多态性实现功能 

2 、使用对象多态性实现功能


 

一 、对象转型 

面对对象有三大特征:封装性、继承性、多态性。而多态性在面向对象中是一个最重要的概念,在Java中面向对象主要有以下两种主要体现:

(1)方法的重载与覆写

(2)对象的多态性

对象的多态性主要分为以下两种类型:

(1)向上转型:子类对象 → 父类对象

(2)向下转型:父类对象 → 子类对象

【对象转型格式】

对象向上转型:父类 父类对象 = 子类实例

对象向下转型:子类 子类对象 = (子类)父类实例

 1 、对象的向上转型

class A{
    public void fun1(){
        System.out.println("A --> public void fun1(){}");
    }
    public void fun2(){
        this.fun1();
    }
}

class B extends A{
    public void fun1(){  //覆写父类A的fun1方法
        System.out.println("B --> public void fun1(){}");
    }
    public void fun3(){
        System.out.println("B --> public void fun3(){}");
    }
}

public class PolDemo01 {
    public static void main(String[] args) {
        B b = new B();  //实例化子类对象
        A a = b ;   //对象向上转型:父类 父类对象 = 子类实例
        a.fun1();   //此方法被子类覆写过
    }
}

程序运行结果:

从程序运行结果发现,发生向上转型后,父类对象实际上调用的是被子类覆写过的方法,如果子类没有覆写父类的方法,则父类对象调用自己的方法,同时要注意:此时父类对象a是无法调用到B类中的fun3()方法的,因为此方法只在子类中定义,而没有在父类中定义。

也就是说,以前对象只能调用自己类中的方法,发生向上转型关系后,父类对象不仅可以调用自己类中的方法,还可以调用子类中覆写父类的方法 

而向下转型之后,子类对象可以调用子类、父类中的所有方法

2 、对象的向下转型

class A{
    public void fun1(){
        System.out.println("A --> public void fun1(){}");
    }
    public void fun2(){
        this.fun1();
    }
}

class B extends A{
    public void fun1(){   //覆写父类A的fun1()方法
        System.out.println("B --> public void fun1(){}");
    }
    public void fun3(){
        System.out.println("B --> public void fun3(){}");
    }
}

public class PolDemo01 {
    public static void main(String[] args) {
        A a = new B();  //发生向上转型
        B b = (B)a;     //发生向下转型
        b.fun1();
        b.fun2();
        b.fun3();
    }
}

程序运行结果:

如果子类B没有覆写父类A的方法,则子类对象b将调用父类A中的fun1()方法,代码如下:

class A{
    public void fun1(){
        System.out.println("A --> public void fun1(){}");
    }
    public void fun2(){
        this.fun1();
    }
}

class B extends A{
    public void fun3(){
        System.out.println("B --> public void fun3(){}");
    }
}

public class PolDemo01 {
    public static void main(String[] args) {
        A a = new B();  //发生向上转型
        B b = (B)a;     //发生向下转型
        b.fun1();
        b.fun2();
        b.fun3();
    }
}

程序运行结果:

也就是说,以前对象只能调用自己类中的方法,发生向上转型关系后,父类对象不仅可以调用自己类中的方法,还可以调用子类中覆写父类的方法 

而向下转型之后,子类对象可以调用子类、父类中的所有方法

两者都是先找被覆写过的方法,没有再调用原方法

 

观察以上程序向下转型过程:

    public static void main(String[] args) {
        A a = new B();  //发生向上转型
        B b = (B)a;     //发生向下转型
        b.fun1();
        b.fun2();
        b.fun3();
    }

注意:在进行对象向下转型前,必须先进行对象向上转型,否则将出现对象转换异常

如下代码所示: 

class A{
    public void fun1(){
        System.out.println("A --> public void fun1(){}");
    }
    public void fun2(){
        this.fun1();
    }
}

class B extends A{
    public void fun3(){
        System.out.println("B --> public void fun3(){}");
    }
}

public class PolDemo01 {
    public static void main(String[] args) {
        A a = new A();  //错误 ,向下转型之前没先向上转型 
        B b = (B)a;     //发生向下转型
        b.fun1();
        b.fun2();
        b.fun3();
    }
}

程序编译报错:类转换异常

 为什么会出现异常呢?先从父类的定义来看:

class A{
    public void fun1(){
        System.out.println("A --> public void fun1(){}");
    }
    public void fun2(){
        this.fun1();
    }
}

从父类的定义来看,父类它本身并不确定谁是自己的子类,它不像 class B extends A{ } 这样明确确定B 继承A,为A的子类。所以直接进行向下转型就会出现类转换异常,此时,需要将两个对象建立关系,通过向上转型,“A a = new B()”,由子类去实例化父类对象,这时父类就知道自己有这么一个子类,再进行向下转型 

 

 

二 、对象多态性的应用

设计一个方法,要求此方法可以接收父类的任意子类对象,并调用方法

1 、不使用对象多态性实现功能 

class A{					// 定义类A
    public void fun1(){		// 定义fun1()方法
        System.out.println("A --> public void fun1(){}") ;
    }
    public void fun2(){
        this.fun1() ;		// 调用fun1()方法
    }
};
class B extends A{
    public void fun1(){		// 此方法被子类覆写了
        System.out.println("B --> public void fun1(){}") ;
    }
    public void fun3(){
        System.out.println("B --> public void fun3(){}") ;
    }
};
class C extends A{
    public void fun1(){		// 此方法被子类覆写了
        System.out.println("C --> public void fun1(){}") ;
    }
    public void fun5(){
        System.out.println("C --> public void fun5(){}") ;
    }
};
public class PolDemo04{
    public static void main(String asrgs[]){
        fun(new B()) ;	// 传递B的实例
        fun(new C()) ;	// 传递B的实例
    }
    public static void fun(B b){
        b.fun1() ;		// 调用覆写父类中的fun1()方法
    }
    public static void fun(C c){
        c.fun1() ;		// 调用覆写父类中的fun1()方法
    }
};

程序运行结果:

不使用对象多态性可以实现功能,但是每增加一个子类,fun()方法就得重载一次。

 

2 、使用对象多态性实现功能

class A{					// 定义类A
    public void fun1(){		// 定义fun1()方法
        System.out.println("A --> public void fun1(){}") ;
    }
    public void fun2(){
        this.fun1() ;		// 调用fun1()方法
    }
};
class B extends A{
    public void fun1(){		// 此方法被子类覆写了
        System.out.println("B --> public void fun1(){}") ;
    }
    public void fun3(){
        System.out.println("B --> public void fun3(){}") ;
    }
};
class C extends A{
    public void fun1(){		// 此方法被子类覆写了
        System.out.println("C --> public void fun1(){}") ;
    }
    public void fun5(){
        System.out.println("C --> public void fun5(){}") ;
    }
};
public class PolDemo04{
    public static void main(String asrgs[]){
        fun(new B()) ;	// 传递B的实例,产生向上转型
        fun(new C()) ;	// 传递B的实例,产生向上转型
    }
    public static void fun(A a){  //接收父类对象
        a.fun1() ;		
    }
};

 程序运行结果:

 从以上程序可以发现,fun()方法使用了对象多态性,可以接收任意的子类对象,这样无论子类如何增加,fun()方法都不用改变。因为子类对象发生向上转型关系,此时父类a调用被子类覆写过的方法

<think>好的,我需要回答用户关于Java对象多态性的体现方式和示例的问题。首先,我应该回顾用户提供的引用内容,看看有哪些相关的信息可以利用。 根据引用[1],多态性是OOP的核心概念,允许同一接口在不同对象上有不同实现。引用[2]提到多态分为编译时多态(方法重载)和运行时多态(方法重写)。而用户特别关注的是对象多态性,这可能更偏向运行时多态,即通过继承和方法重写实现。 引用[4]指出,实现多态需要三个条件:继承、重写和向上转型。因此,示例需要展示这三个要素。比如,创建一个父类和子类,子类重写父类方法,然后通过父类引用指向子类对象,调用方法时实际执行子类的方法。 用户需要具体的示例,所以应该用代码来说明。比如,Animal类作为父类,Cat和Dog作为子类,重写eat方法。然后创建父类类型的变量指向子类实例,调用eat方法时会根据实际对象类型执行对应的方法,这就是运行时多态。 另外,引用[3]提到集合框架中的多态性,比如使用List接口引用ArrayList或LinkedList。可能可以加入这样的示例,展示多态在集合中的应用,比如List list = new ArrayList<>();,这里体现了接口的多态性。 需要注意的是,用户可能混淆了方法重载和对象多态。根据引用[2],方法重载是编译时多态,而用户的问题更关注对象多态,即运行时多态。因此,示例应侧重于继承和重写,而不是重载。 另外,可能需要解释向上转型的概念,即父类引用指向子类对象,这是实现多态的关键步骤。同时,多态的应用场景,比如在方法参数中接收父类类型,可以传入任何子类对象,增加代码的灵活性。 现在,组织这些思路,先定义多态性的体现方式,然后给出继承与重写的示例,接着是接口与实现类的示例,再结合集合框架的例子,最后总结多态的优势。确保每个示例都符合引用的内容,并在适当的地方添加引用标记。</think>### Java对象多态性的体现方式及示例 Java中的**对象多态性**主要通过**继承关系**和**方法重写**实现,具体表现为**父类引用指向子类对象**,并在运行时根据实际对象类型调用对应方法。其核心是**运行时绑定**(动态绑定)机制,满足以下三个条件:继承、重写、向上转型[^4]。 --- #### 一、多态性的典型体现 1. **方法重写(运行时多态)** 子类重写父类方法后,通过父类引用调用该方法时,实际执行的是子类的方法实现。 2. **向上转型(Upcasting)** 父类引用指向子类对象,例如:`Animal dog = new Dog();`。 3. **接口与实现类** 接口类型的引用可以指向不同实现类的对象,例如:`List list = new ArrayList<>();`。 --- #### 二、具体示例 ##### 示例1:继承与方法重写 ```java // 父类 class Animal { public void eat() { System.out.println("动物进食"); } } // 子类1 class Cat extends Animal { @Override public void eat() { System.out.println("猫吃鱼"); } } // 子类2 class Dog extends Animal { @Override public void eat() { System.out.println("狗啃骨头"); } } public class Test { public static void main(String[] args) { Animal animal1 = new Cat(); // 向上转型 Animal animal2 = new Dog(); // 向上转型 animal1.eat(); // 输出:猫吃鱼(实际调用Cat类的方法) animal2.eat(); // 输出:狗啃骨头(实际调用Dog类的方法) } } ``` **说明**: - `Animal`类型的引用`animal1`和`animal2`分别指向`Cat`和`Dog`对象。 - 调用`eat()`方法时,JVM根据对象的实际类型决定执行哪个子类的方法[^2]。 --- ##### 示例2:接口多态性 ```java interface Shape { void draw(); } class Circle implements Shape { @Override public void draw() { System.out.println("绘制圆形"); } } class Rectangle implements Shape { @Override public void draw() { System.out.println("绘制矩形"); } } public class Test { public static void main(String[] args) { Shape shape1 = new Circle(); Shape shape2 = new Rectangle(); shape1.draw(); // 输出:绘制圆形 shape2.draw(); // 输出:绘制矩形 } } ``` **说明**: - 接口`Shape`的引用可以指向不同实现类对象,调用`draw()`时体现多态性[^3]。 --- ##### 示例3:集合框架中的多态性 ```java List<String> list = new ArrayList<>(); // 接口引用指向ArrayList list.add("Java"); list = new LinkedList<>(); // 同一接口引用切换为LinkedList list.add("Python"); ``` **说明**: - 通过`List`接口统一操作不同实现类(如`ArrayList`和`LinkedList`),代码更灵活[^3]。 --- #### 三、多态性的优势 1. **代码扩展性**:新增子类时无需修改原有代码(如新增`Bird extends Animal`)。 2. **统一接口**:通过父类或接口统一处理不同子类对象。 3. **降低耦合**:调用方仅依赖抽象层(父类/接口),不依赖具体实现。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值