继承、重载、覆盖、多态

1、继承(inheritance)
   一旦你已经创建了一个定义了对象一般属性的超类,该超类可以被继承以生成特殊用途的类。每一个子类只增添它自己独特的属性。这是继承的本质。Java 不支持多超类的继承。
   超类变量可以引用子类对象(这个具体有什么作用,有待补充)
2、重载(overload)
   a)、方法重载要求参数类型或个数必须不一致
   b)、对返回类型无限制
   c)、对于继承来说,如果某一方法在父类中是访问权限是priavte,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。
 
3、覆盖(override)
   从字面就可以知道,它是覆盖了一个方法并且对其重写,以求达到不同的作用。对我们来说最熟悉的覆盖就是对接口方法的实现,在接口中一般只是对方法进行了声明,而我们在实现时,就需要实现接口声明的所有方法。除了这个典型的用法以外,我们在继承中也可能会在子类覆盖父类中的方法。在覆盖要注意以下的几点: 
   a)、要求父类和子类的方法名称、参数相同
   b)、子类中覆盖的方法的访问权限要>=父类中的方法的访问权限(defautl、protected、public)。
   c)、子类中覆盖的方法的返回值必须和父类中的方法的返回一致; 
   d)、子类中覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类; 
   e)、被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。
   f)、静态方法和最终方法(带关键字final的方法)不能被覆盖(“实例方法被覆盖,静态方法被隐藏”)
   g)、抽象方法必须在具体类中被覆盖
4、多态(polymorphism)
   多态性的概念也可以被说成“一个接口,多个方法”。Java实现运行时多态性的基础是动态方法调度,它是一种在运行时而不是在编译期调用重载方法的机制。
   多态的通常含义是能够呈现出多种不同的形式或形态,即一个特定类型的变量可以用于引用不同类型的对象,并且自动调用该变量引用的特定类型对象的方法,这样就使得一个方法的调用根据该调用所作用到的不同对象类型而响应不同的操作。
   下面就继承和接口实现两方面谈谈java运行时多态性的实现。
   (1)、通过继承中超类对象引用变量引用子类对象来实现
       //定义超类superA
       class superA
       {
         void callfun()
         {
            System.out.println("call superA");
         }
       }
     
      // 定义superA的子类subB
      class subB extends superA
      {
        void callfun()
        {
           System.out.println(call subB");
        }
      }
 
      // 定义superA的子类subC
      class subC extends superA
      {
        void callfun()
        {
           System.out.println("call subC");
        }
      }
 
      class mytest
      {
        public static void main(String[] args)
        {
           superA a;
           subB b = new subB();
           subC c = new subC();
           a=b;
           a.callfun();  (1)
           a=c;
           a.callfun();  (2)
        }
      }
 
     运行结果:
     call subB
     call subC
   
     上述代码中subB和subC是超类superA的子类,我们在类mytest中声明了3个引用变量a, b, c,通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。也许有人会问:“为什么(1)和(2)不输出:call superA”。java 的这种机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
   所以,不要被上例中(1)和(2)所迷惑,虽然写成a.callfun(),但是由于(1)中的a被b赋值,指向了子类subB的一个实例,因而(1)所调用的callfun()实际上是子类subB的成员方法callfun(),它覆盖了超类superA的成员方法callfun();同样(2)调用的是子类subC的成员方法callfun()。
   另外,如果子类继承的超类是一个抽象类,虽然抽象类不能通过new操作符实例化,但是可以创建抽象类的对象引用指向子类对象,以实现运行时多态性。具体的实现方法同上例。
   不过,抽象类的子类必须覆盖实现超类中的所有的抽象方法,否则子类必须被abstract修饰符修饰,当然也就不能被实例化了。

有人不禁要问,子类重写了父类的方法,为什么不直接用子类创建引用来引用子类的对象,而非要用父类创建个引用来引用子类的对象呢?这不是多此一举吗?
   直接用子类创建引用当然可以,但是这无法体现出Java多态的优势。
   举个例子,一个公司要派员工出差解决问题,员工里面有资深员工,有新手,资深员工解决问题的能力当然比新手强了,我们设计几个类
   class Staff
   {
      void resolve()
      {
         System.Out.Println("为客户解决问题");
      }
   }

   class ExperienceStaff extends Staff  //资深员工,能快速解决问题
   {
      void resolve()
      {
         System.Out.Println("快速地为客户解决问题");
      }
   }

   class NewStaff extends Staff  //新手,无法单独解决问题
   {
      void resolve()
      {
         System.Out.Println("我是菜鸟,需要别人帮助才能解决问题");
      }
   }
 
   //现在客户说产品有问题,要公司派人给解决
   class Customer
   {
      void resolveProblem(Staff sf)
      {
         sf.resolve();
      }
   }
 
   //测试
   Public class Test
   {
      public static void main(String[] args)
      {
         Customer cs = new Customer();
     
         Staff guy = new ExperienceStaff();
         cs.resolveProblem(guy);  //给客户派去一个资深员工,迅速解决了问题,客户很满意
     
         guy = new NewStaff();       
         cs.resolveProblem(guy);  //给客户派去一个新手,不停的打电话请教别人,客户很生气,后果很严重
      }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值