一、什么是继承 1、在程序中,可以使用extends关键字让一个类继承另外一个类。 2、继承的类为子类(派生类),被继承的类为父类(超类, 基类)。 3、子类会自动继承父类所有的方法和属性。 二、为什么要使用继承 1、当我们发现一个类的功能不行,方法不够用时,就可以派生子类,增加方法。 2、当我们需要定义一个能实现某项特殊功能的类时,就可以使用继承。 3、最终还是为了一个目的,提高代码的复用性。 总结:当我们定义一个类时,发现另一个类的功能这个类都需要,而这个类又要增加一些新功能时,就可以使用extends关键字继承那个类, 这样那个被继承类的功能就都有了,不必重写编写代码。这时只要在新的类中编写新的功能即可,原有代码就被复用了。 三、继承的特点 Java只支持单继承,不支持多继承,但是可以多重继承。 原因:因为如果一个类继承多个类,多个类中有相同的方法,子类调用该方法时就不知道该调用哪一个类中的方法了。 四、向上转型 从以下三个方面来理解: 1、把一个子类当做父类来用是可以的,因为父类有的子类都有 2、把一个父类当做子类来用就不可以了,因为子类有的父类不一定有 3、可以定义一个父类类型的变量来记住子类对象,这在程序中称之为向上转型 五、强制类型转换 1、 把一个子类当做父类来用的时候,不能调用子类特有方法。 因为编译时编译器会做语法检查,看到变量是父类类型那么就会到父类中查找是否有该方法,没有则报错。 这种情况下,就需要强制类型转换,将父类类型强转成子类类型。 2、以(子类名)变量名形式进行强制类型转换 强制类型转换时,无论类型是否匹配编译都不会报错,但如果类型不匹配运行会报错,我们可以使用instanceof进行判断,编译时预知错 误。 总结:在子类当做父类来用时,不能调用特有方法,如果一定要调用,就需要强制类型转换回子类。在做转换时最好instanceof判断一下类型 是否匹配。 六、子类覆盖(Override)父类方法 从以下方面理解: 1、 覆盖方法必须和被覆盖方法具有相同的方法名称、参数列表和返回值类型。 2、 子类的方法返回值类型可以是父类方法返回值类型的子类。 3、 如果在子类中想调用父类中的那个被覆盖的方法,我们可以用super.方法的格式。 4、 如果直接调用方法,是在当前子类中先查找,如果子类有会调用子类的。使用super形式只在父类中查找,子类有没有都不调用。 5、 覆盖方法时,不能使用比父类中被覆盖的方法更严格的访问权限。 6、 因为有可能将子类对象当做父类对象来使用,那么能获取到的父类对象中的方法在子类中必须都能获取到。 7、 覆盖方法时,不能比父类抛出更多的异常。 8、 子类只能比父类强,不能比父类弱。 注意:重载(Overload)和重写(Override)的区别? 1、重载是方法名相同,参数列表不同,和返回值类型无关。 2、重写是方法名、参数列表、返回值类型全相同。 @Override 注解,可以检查覆盖是否成功 七、继承的应用细节 1、子类不继承父类私有成员 2、父类中私有成员对外不可见,子类对象中无法访问这些成员。 3、构造函数不被继承 4、构造函数通常用来初始化类的成员变量,父类和子类的成员变量不同,初始化方式也不同,构造函数的名字也不同。 八、子类对象实例化过程 1、子类构造函数中可以使用super关键字调用父类构造函数。 2、在子类创建对象时一定会调用父类构造函数。即使没有显式调用,也会默认调用父类无参构造函数。 3、在子类中第一行用this关键字去调其他的构造方法,这时系统将不再自动调父类的。但其他构造函数中会调用父类构造函数。 4、在构造方法中this和super关键字只能出现一次,而且必须是第一个语句。 以后在设计类的时候,最好定义一个无参的构造方法,不然子类实例化的时候就容易出错。 九、子类当做父类使用时需要注意 当我们在调用某个类的一个方法时,此方法声明需要一个父类对象,这时我们可以将一个子类对象作为实参传递过去,注意此时方法定义的形参为父类,在方法中使用父类变量调用方法时,其实是调用子类的方法。 思考:上述情形下,在方法中用父类变量访问属性,访问的是子类还是父类的属性 ? 在把子类当做父类来用时,使用父类变量访问方法,访问的是子类的方法,因为虚拟机会找到变量引用的地址,根据这个地址来访问方法,这叫动态分配。这种机制没有被使用到类的成员变量上,如果用父类变量访问属性,那么会直接找到父类的属性,不会看地址是哪个对象。
|