Java面向对象编程之继承(二)

在上一篇博客中,我们已经了解继承的基本概念和语法,那么今天我们就来聊一聊有关于继承的其他东西。

让我们来了解一下什么是方法重载(overload)和方法覆盖(override)

方法重载(overload)

对于类的的方法(包括从父类中继承的方法),如果有两个方法的方法名相同,但参数不一致,那么可以说,一个方法是另一个方法的重载方法。

重载方法必须满足以下条件:

  • 方法名相同
  • 方法的参数类型、个数、顺序至少有一项不相同
  • 方法的返回类型可以不相同
  • 方法的修饰符可以不相同

其中,参数的类型、个数和顺序被统称为参数签名。来看一下例子:

public class Example{
    public void amethod(int i ,String s){} //实例方法
    // 加入其它方法
    public void amethod(int i,String s){} //不可以,因为这个方法和我们定义的实例方法一模一样,Java虚拟机在执行时不知道该执行哪一个
    public void amethod(String s,int i){} //可以,属于重载方法,参数的顺序不一样
    public int amethod(int i,String s){return 0;} //不可以,虽然方法的返回类型不相同,但是方法名和参数签名完全一致,所以这不能算是重载方法,不能加到Example中
    public private amethod(int i,String mystring){} //不可以,方法名和参数签名相同,所以这也不能算是重载方法
    public void Amethod(int i,String s){} //方法名不一样,是一个新的实例方法,所以可以加入到Example类中
    abstract void amethod(int i){} //不可以,该方法的参数数目和已有的不一样,所以是一种重载方法。但是Example类不是抽象类,所有不能加入这个抽象方法。倘若将Example类改为抽象类。则可以加入这个方法
}

 另外,作为程序入口的main()方法也可以被重载。

方法覆盖(override)

如果子类中定义的一个方法,其名称、返回类型及参数签名正好与父类中某个方法的名称、返回类型及参数签名相匹配,那么可以说,子类的方法覆盖了父类的方法。

覆盖方法必须满足多种约束,下面分别介绍:

  1. 子类方法的名称、参数签名和返回类型必须与父类方法的名称、参数签名和返回类型一致。
  2. 子类方法不能缩小父类方法的访问权限,这是什么意思呢?我们可以看下面这个例子:
    public class A extends B{
        private void method(){} //编译错误,子类方法缩小了父类方法的访问权限
    }
    
    class B{
        public void method(){}
    }

     子类的method()方法是私有的,父类中的method()方法是公有的,子类缩小了父类方法的访问权限,这是无效的方法覆盖,会导致编译错误。

  3. 子类方法不能抛出比父类方法更多的异常。子类方法抛出的异常必须和父类方法抛出的异常相同,或者是父类方法抛出的异常的子集。
  4. 方法覆盖只存在于子类和父类(包括直接父类和间接父类)之间,在同一个类中方法只能被重载,不能被覆盖。
  5. 父类的静态方法不能被子类覆盖为非静态方法。
  6. 子类可以定义同父类的静态方法同名的静态方法,以便在子类中隐藏父类的静态方法。在编译时,子类定义的静态方法也必须满足和方法覆盖类似的约束:方法的参数签名一致,返回类型一致,不能缩小父类方法的访问权限,不能抛出更多的异常。
  7. 父类的非静态方法不能被子类覆盖为静态方法。
  8. 父类的私有方法不能被子类覆盖。
  9. 父类的抽象方法可以被子类通过两种途径覆盖:一是子类实现父类的抽象方法;二是子类重新声明父类的抽象方法。例如以下代码合法:
abstract class Base(){
    abstract void method1();
    abstract void method2();
}

public abstract class Sub extends Base(){
    public void method1(){...}; //实现method1()方法,并且扩大访问范围
    public abstract method2(){}; //重新声明method2()方法,仅仅扩大访问权限,但不实现
}

  10.父类的非抽象方法可以被覆盖为抽象方法。

狭义地理解,覆盖仅指子类覆盖父类的具体方法,即非抽象方法,在父类中提供了方法的默认实现方式,而子类采用不同的实现方式。

方法覆盖与方法重载的异同

方法覆盖和方法重载具有以下相同点:

  • 都要求方法同名。
  • 都可以用于抽象方法和非抽象方法之间。

方法覆盖和方法重载具有以下不同点:

  • 方法覆盖要求参数签名必须一致,而方法重载要求参数签名必须不一致。
  • 方法覆盖要求返回类型必须一致,而方法重载对此不作限制。
  • 方法覆盖只能用于子类继承父类的方法,方法重载用于同一个类的所有方法,包括从父类中继承而来的方法。
  • 方法覆盖对方法的访问权限和抛出的异常有特殊的要求,而方法重载在这方面没有限制。
  • 父类的一个方法只能被子类覆盖一次,而一个方法在所在的类中可以被重载多次。

 

posted @ 2017-07-31 20:20  noob_coder  阅读(181)  评论(0编辑  收藏  举报