继承和多态
一.继承
1.继承的理解:继承简单地说就是将很多类中的共同属性放在一个类中,在这些很多类中通过继承就可以使用这个属性,这样可以不用重复的写相同的代码。
2.继承的关键字是extends。
这个是具有共同属性的类(这种类称为父类或者基类或者超类):
这是需要使用到共同属性的类(这种类称为子类或者派生类):
这也是需要用到共同属性的类(这种类称为子类或者派生类):
3.如果子类和父类没有什么不同的话就没必要继承了。
4.子类中的成员变量与父类中 的成员变量同名时,会先用子类的成员变量。
5.如果非要访问父类中同名的成员变量那就需要用到super关键字
这就是访问同名父类中的成员变量的关键字super的用法:
6.子类继承父类中的方法也是和继承父类的成员方法一样的。如果父类和子类的方法名同名的时候一定要用使用父类中的方法时super.方法名就可以使用父类中的方法。
7.在静态方法中不能使用this和super关键字。
8.当子类继承了父类之后,在实例化子类的对象之前,要先帮助父类进行构造。(初始化父类的成员,但是初始化父类的成员并不会实例化一个父类的对象!)
9.当父类中有了用户自己设置了一个构造方法的时候,需要用户在子类中也写出一个构造方法来先进行初始化父类的成员。
这里在父类中写了一个构造方法子类就会报错了,因为没有在子类中进行初始化父类中的成员:
此时应该在子类中构造一个方法,并且在方法里面给通过super来调用父类中的构造方法来初始化父类:
10.之前没有报错是因为我们原来没有在父类中自己定义一个构造方法,但是编译器会默认构造一个父类的构造方法,子类中也会默认构造一个父类的构造方法。也就是下面的们写出的构造方法:
11.super()和this()调用构造方法的时候都要放在代码的第一行,所以不能同时存在。并且super只能出现一次。
12.父类的静态代码块先执行其次是子类的静态代码块,再然后就是父类的实例代码块和构造方法,最后才是子类的实例代码块和构造方法。(静态代码块还是只出现一次):
二.protected关键字
1.可以在同一个包中同一个类中访问。
2.可以在同一个包中的不同类中访问。
3.可以在不同包的的子类中访问。
这是父类的包:
子类的包,但是需要注意的是不能在直接这样的访问父类中的成员变量。需要通过特殊手段:
通过写一个方法在加上关键字super就可以调用了:
不能在main方法中直接用super来访问的原因是因为main方法是静态方法,而super关键字不能在静态中使用。(需要注意的继承的父类只能是public修饰的),类的权限只有public和包访问权限。
三.继承的方式
1.单继承:
2.多层继承:
3.不同类继承同一个类:
4.多继承:(java不支持):
四.final关键字
1.修饰变量或者字段,变成常量就不能修改:
2.修饰类,表示此类不能继承:
3.修饰方法,方法就不能被重写:
五.继承和组合
1.将一个类作为另外一个类的实例:
六.多态
1.概念:同一个行为,不同的对象就会有不同的结果。
2.向上转型
1.概念:将子类生成的对象传给父类:(两种方法都可以):
2.不能访问父类没有的方法(通过父类引用访问的时候只能访问父类的方法):
3.向上转型的方法:
(1).直接赋值:在概念的地方已经有过截图。
(2).方法传参:
(3).返回值:
4.优点:代码实现更加简单灵活;缺点:不能调用子类特有的方法。
3.方法重写
1.方法名相同。
2.方法的参数列表相同(个数,顺序,类型)。
3.方法的返回值相同:
4.重写的注解,修饰该方法,该方法就是重写,帮你检查是否重写:
5.静态方法不能被重写。
6.被private修饰的方法不能被重写。
7.被final.static修饰的方法(密封方法)不能被重写。
8.子类的访问权限要大于等于父类的权限。
9.协变类型:(特殊的重写,方法的返回值是父子类关系):
4.动态绑定
1.必须放生向上转型,并且通过父类引用子类对象。
2.在通过父类引用来调用重写的方法:
3.编译的时候调用的是父类的方法,当时运行的时候是调用的子类的方法。
5.静态绑定
1.在编译的时候就确定调用那个方法了:
6.多态的实现
1.多态的代码实现:
2.多态实现的解释:当animal引用的对象不一样,(这里是把new 之后的两个不同的对象给了同一个引用,这个引用就是animal。)调用了eat的方法,表现的行为就不一样。此时就叫做多态。因为同一个引用,调用同一个方法,结果不相同。
3.优点:降低代码的“圈复杂度”,避免大量的if-else。比如这样:(其中画了圈的位置多加留意)还有就是它的可扩展能力强。(需要增加时直接创一个新的类就可以了,不需要if-else那么麻烦的进行一定的修改)
4.圈复杂度介绍:
5.缺点:实行的代码效率低。(1.属性没有多态性,父类和子类的方法同名,通过父类的引用却只能使用父类的方法。2.构造方法没有多态性。
7.避免在构造方法当中调用重写的方法(简单了解)
首先是进入了D的构造方法中,这里的D用户没有自己写构造方法,系统会有默认的构造方法,在实现完子类的构造方法之前,会先去实现父类的构造方法,但是在父类的构造方法中,实现了func方法的重写,这里也就说明了,构造方法也可以发生动态绑定。当func实现之后,num还没有被完全初始化,因为子类的构造都还没有完成,此时才执行完父类的构造,所以num的值此时还是0.