Java 多态

java 多态

1.多态释义

多态是指同一操作用于不同的类的实例,不同的类将进行不同的解释,最后产生不同的结果,也就是,相同的语句在不同的运行环境中可以产生不同的运行结果。

多态的本质特征就是父类(或接口)变量可以引用子类(或实现接口的类)对象,也就是子类对象可以被当做基类对象使用。

Parent p=new Child1();
Parent p=new Child2();

总是可以让更一般的对象容纳更具体的对象

子类与基类间的赋值:

子类对象可以直接赋给基类变量,但是基类对象要想赋给子类变量必须执行类型转换,语法为:

子类变量=(子类名)基类对象名;

这种转换失败会抛出ClassCastException异常。通过instanceof判断对象是否可转换为指定类型。

下面代码便于理解类型转换:

public class TestMain {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Parent parent=new Parent();
        parent.printVal();//100
        Child child=new Child();
        child.printVal();//200

        parent=child;
        parent.printVal();//200,调用子类方法

        parent.val++;//父类字段
        System.out.println(parent.val);//101
        parent.printVal();//200,子类方法

        ((Child)parent).val++;//子类字段
        parent.printVal();//201//子类方法

    }

}

class Parent{
    public int val=100;
    public void printVal(){
        System.out.println("Parent.printVal,val="+val);
    }
}
class Child extends Parent{
    public int val=200;
    public void printVal(){
        System.out.println("Childs.printVal,val="+val);
    }
}

总结一下输出这样结果的原因:

1.子类与父类有同名方法时:

一个父类变量引用一个子类对象时,具体调用哪个方法由对象”真实”类型决定,就是说,对象是子类型就调用子类型方法,是父类型就调用父类型方法。

2.子类父类具有同类型同名字段时:

子类字段会隐藏父类字段,子类方法访问的是子类字段(而不是父类字段)。如果子类确实想访问父类字段,可以用super关键字访问。

但如果子类被当做父类使用,即父类变量名子类对象,则访问的字段是父类的。

注意当把子类对象当成父类对象使用时,子类对象将失去所有的子类特性,只保留与父类同名的属性和方法(同名方法不仅是函数名相同,而且参数类型也要一样,否则不予保留)。

下面举个例子来说明多态的使用:

动物类:
public class Animal {
    public void cry(){
        System.out.println("我不知道叫什么");
    }
    public void eat(){
        System.out.println("我不知道吃什么");
    }
}
猫类:
public class Cat extends Animal{

    public void cry(){
        System.out.println("喵喵");
    }

    public void eat(){
        System.out.println("我是猫,我吃鱼");
    }
}
狗类:
public class Dog extends Animal{

    public void cry(){
        System.out.println("旺旺");
    }

    public void eat(){
        System.out.println("我是狗,我吃骨头");
    }

}

食物接口:
public interface Food {
    public void showName();
}
食物骨头:
public class Bone implements Food {

    @Override
    public void showName() {
        // TODO Auto-generated method stub
        System.out.println("食物:骨头");
    }

}
食物鱼:
public class Fish implements Food {

    @Override
    public void showName() {
        // TODO Auto-generated method stub
        System.out.println("食物:鱼");
    }

}
主人类:
public class Master {
    public void feed(Animal an,Food f){
        an.eat();
        f.showName();
    }
}

测试:
public class TestMain {

    public static void main(String[] args) {

        Master master=new Master();
        master.feed(new Dog(), new Bone());
        master.feed(new Cat(), new Fish());
    }

}

输出:
我是狗,我吃骨头
食物:骨头
我是猫,我吃鱼
食物:鱼

可以看出多态在代码量非常巨大的时候,当需要修改代码或扩展系统时需要修改的地方非常少。

再来一份代码练习:

public class TestMain {

    public static void main(String[] args) {
        A a1=new A();
        A a2=new B();
        B b=new B();
        C c=new C();
        D d=new D();

        System.out.println(a1.show(b));//b是a子类,调用show2
        System.out.println(a1.show(c));//c是a子类,调用show2
        System.out.println(a1.show(d));//d就是D,调用show1

        //a2是A变量名,B对象,应调用B方法覆盖掉A的方法即B的第二个show,B自身特性消失
        System.out.println(a2.show(b));//show3消失,show4覆盖show1,故调用show4
        System.out.println(a2.show(c));//同上
        System.out.println(a2.show(d));//直接调用show1

        System.out.println(b.show(b));//原生B,直接用show3,4
        System.out.println(b.show(c));//同上
        System.out.println(b.show(d));//由于B也有A的属性,故含有show1方法,所以调用show1

    }

}
class A
{
    public String show(D obj){//show1
        return ("A and D");
    }
    public String show(A obj){//show2
        return ("A and A");
    }
}
class B extends A
{
    public String show(B obj){//show3
        return ("B and B");
    }
    public String show(A obj){//show4
        return ("B and A");
    }
}
class C extends B{

}
class D extends B{

}

输出:

A and A

A and A

A and D

B and A

B and A

A and D

B and B

B and B

A and D

参考:

金旭亮Java编程系列

https://www.cnblogs.com/mz-lover/p/4786337.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值