Java基础提高篇(二)多态

在面向对象的程序设计语言中,多态是继数据抽象和继承之后的第三种特征。

不同类的对象对同一消息作出不同的响应就叫做多态。

多态存在的三个条件

1、有继承关系  

2、子类重写父类方法  

3、父类引用指向子类对象

多态方法调用允许一种类型表现出与其他相似类型之间的区别,只要它是从同一基类导出而来的,这种区别是根据方法行为的不同而表现出来的,虽然这些方法都可以通过同一个基类来调用。

看一个简单的多态例子

enum Ball{
    BASKETBALL,FOOTBALL
}
class Sport{
    public void play(Ball ball){
        System.out.println("Sport------"+ball);
    }
}
class BaskSport extends Sport{
    @Override
    public void play(Ball ball) {
        System.out.println("BaskSport-------"+ball);
    }
}

public class Demo1 {
    public static void p(Sport s){
        s.play(Ball.BASKETBALL);
    }
public static void main(String[] args) {
        BaskSport baskSport=new BaskSport();
        p(baskSport);
    }
}

输出: BaskSport——-BASKETBALL

Demo1.p()接收一个Sport引用,同时也可以接收任何Sport的导出类,当将BaskSport引用传递给p()时,由于这是向上转型,是允许的,向上转型可能会缩小接口,但不会比父类的全部接口更窄。

多态的二个缺陷
1.“覆盖”私有方法
public class Demo1 {
private void fun(){
    System.out.println("Demo1的私有fun方法");
}   
public static void main(String[] args) {
        Demo1 demo1 = new Zi();
        demo1.fun();
    }
}
class Zi extends Demo1{
    public void fun(){
        System.out.println("Zi的fun方法");
    }
}

输出:Demo1的私有fun方法

按道理,应该输出”Zi的fun方法”才对,但是这里有个陷阱就是Demo1的fun方法是私有的,无法被覆盖,而Zi类中的fun是新的方法。所以:只有非private方法才可以被覆盖。

2.域和静态方法

只有普通方法的调用可以是多态的,域和静态方法不能是多态的。

class NBA{
    public String location="USA";
    public void f(){
        System.out.println(location);
    }
}
class CBA extends NBA{
    public String location="CBA";
    public void f(){
        System.out.println(location);
    }
}
public class Demo1 {

public static void main(String[] args) {
         NBA nba = new CBA();
         String location = nba.location;
         System.out.println(location);
         nba.f();
    }
}

输出:

USA
CBA

可以看到,当子类对象转型为父类引用时,任何域访问操作都将由编译器解析,因此不是多态的。其实在实际开发过程中,我们不会将域设置为public的,一般设置成private,因此不能直接访问它们,只能通过调用方法访问。

如果某个方法是静态的,它的行为就不具有多态性

class NBA{
    public static void f1(){
        System.out.println("NBA");
    }
    public void f2(){
        System.out.println("NBA----f2");
    }
}
class CBA extends NBA{
    public static void f1(){
        System.out.println("CBA");
    }
    public void f2(){
        System.out.println("CBA----f2");
    }
}
public class Demo1 {

public static void main(String[] args) {
        NBA nba = new CBA();
        nba.f1();
        nba.f2();
    }
}

输出:

NBA
CBA----f2

**
静态方法是与类,而非与单个对象相关联的。**

向下转型
class NBA{
    public void f1(){}
}
class CBA extends NBA{
    public void f1(){}
    public void f2(){}
}
public class Demo1 {

public static void main(String[] args) {
        NBA nba = new NBA();
        nba.f1();
        ((CBA)nba).f2();
    }
}

重点是这句:((CBA)nba).f2();

如果单纯的nba.f2();那么无法编译,因为NBA类并没有f2()方法,所以必须进行向下转型,转换为CBA类型的,因为CBA类型有f2()。

向上转型和向下转型其实很好理解,小的—>大的,大的—>不能说是小的。毕竟中国是上海的,这句话要被笑话的。

友情链接:
谈谈多态

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值