学习内容:
- 继承
- 重写
- 重载
- 封装
- 多态
- 抽象
相关比较:
一、 继承定义:当前类派生出的新的类,当前类称为基类或父类,派生出来的类称之为派生类或者子类,子类会默认继承父类的方法和属性。
关键字:extends 语法:修饰符 class 子类 extends 父类{ 子类代码 }
注意:当子类想继承父类时,父类必须有无参的构造方法,如果不主动添加系统会默认添加一个无参的构造方法,此时子类可以顺利继承父类
但是当父类添加了一个带参的构造方法时,此时系统将不会再默认添加无参的构造方法,所以此时必须自己手动添加一个无参的构造方法,这样才能保证被子类顺利的继承
在实例化子类的时候会自动的实例化父类,如果此时的父类还继承了其他的类,那么便会逐级的向上查询,知道找到顶级的父类,然后开始逐个的实例化,在实例化的同时便会自动调用无参的构造方法,但是如果想要调用父类的带参的构造方法,此时就必须通过super(i)进行调用,即用super指定调用。
补充知识点:
-
类的访问修饰符的作用范围
修饰符 private default protected public
本类 √ √ √ √
同包 × √ √ √
不同包 × × × √ -
继承的访问范围
修饰符 private default protected public
同包 × √ √ √
不同包 × × √ √
总结:继承与类的区别即在不同包时,protected也可以访问
本身类的执行顺序是:静态>属性>构造器 eg:new 一个对象时 先是执行静态部分 然后是属性 最后是构造方法 注意不是函数哦 函数得调用,由此来研究再继承时的子类执行顺序:
首先、子类的构建过程是先构建父类,在构建子类,然后进行关联,默认是超类Object;
于是子类的执行过程:静态最优先 >父类属性 >父类构造器 >子类属性 >子类构造器
注意:1、Java只支持单继承、多实现
继承的优点:优化代码,提高了代码的复用性
继承的缺点:耦合度高,即类与类之间相对独立性降低
优秀的代码秉承的原则:高内聚 低耦合 多聚合 少继承
二、重写定义:当父类的方法不能满足子类的需求时,子类需重写该方法。发生在子类当中**@override**
规则:方法名称相同;参数列表相同;返回类型相同; 修饰符的访问范围必须大于等于父类
补充:super的用法:
①调用构造器:在子类构造器中如果要指定的调用父类构造器需要使用super(参数列表);这句话必须放在第一句
②调用方法:如果子类重写父类方法,指定调用父类被重写方法,使用super.方法名【参数列表】—父类有参数的方法
③调用属性:如果子类重写了父类的属性,使用super super.属性名。
三、重载定义 :在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同甚至是参数顺序不同)则视为重载。同时,重载对返回类型没有要求,可以相同也可以不同,但不能通过返回类型是否相同来判断重载。
总结:重载与重写的区别:
①方法的重载和重写都是实现多态的方式,区别在于重载实现的是编译时的多态性—在编译时已经确定好了,而重写实现的是运行时的多态性—只有在程序运行时才知道调用的是哪个子类的方法。
②重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。
③重载对返回类型没有特殊的要求,不能根据返回类型进行区分。
四、封装定义:将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来对隐藏的信息进行操作和访问。
优点:只能通过规定的方法访问数据,隐藏类的实例细节,方便修改和实现。
实现:
①修改属性的可见性设为(private)
②创建getter/setter方法
五、多态定义: 父类的对象变量调用了子类中重写的方法(注意: 往往是有一个父类,而他有多个子类,且在这些子类中同时重写父类的某个方法);结论:多态的前提是有一个父类,多个子类。
注意: 子类的对象变量不可以引用父类的对象— 若要进行,则必须强制转换
对象类型的转换分为以下两种:1) 向上转型: 子类的对象可以直接赋给父类的对象变量。
这种现象也称之为类型的自动转换。 –父类的对象变量调用了子类中重写的方法
2) 向下转型: 将父类的引用强制转换成子类的引用。--于是可以用子类特有的方法
注意: 它必须强制转换。格式: (类型名) 对象变量;
当父类对象变量引用了子类的对象时,则问: 父类的对象变量是否可以直接调用子类的特有方法?一般而言子类单独定义的方法会丢失,若非要访问则用强制类型转换;
eg:Animal是父类;Dog是子类,run()是子类特有的方法;
若 Animal a = new Dog();
则a.run()是错误的!
于是 强制转换(即向下转型)得到:
Dog b=(Dog)a;
a.run()即可。
什么情况下需要将对象的引用实现强制转换(还原)(向下转型)?
1) 一定是发生多态:
父类的对象变量引用了子类的对象。
Object obj = new Student();
2)**一定是想要去访问(调用)子类对象的特有属性或方法。**
父类的对象变量.子类对象的特有方法(属性); //则错了。
Stringstr = obj.getSchool(); //错了。
((子类类名)父类的对象变量).子类对象的特有方法(属性); //则对了。
Stringstr = ((Student)obj).getSchool(); //对了。
结论: 动态绑定的前提是:
-
发生继承,且一个父类有多个子类。
-
在每一个子类中对继承自父类的同一个方法实现了重写。
-
发生多态,即: 父类对象变量引用了不同的子类对象。
-
父类的对象变量调用了重写的方法,即: 发生了动态绑定。从而实现了多的价值。
注意:父类类型不能转换成子类类型—向下转型时
多态就是 面向接口编程
你没实例化一个对象 就要new一下,那假如你那天改变了需求了呢?那是不是又要改里面的?这样不好,所以 你可以通过多态,把需要相似的给提出来,然后继承它 这样 以后需要扩展你仅仅只是继承而已。这样就很简单。
多态总结:
-
使用父类型的引用指向子类的对象
-
该引用只能调用父类中定义的方法,不能调用子类中独有的方法
-
如果子类中重写了父类中的一个方法,那么在调用该方法的时候,将会调用子类中的方法。
-
在多态中,子类可以调用父类中的所有方法。
-
可以用 instanceof 比较对象是不是某种类型 返回值是true 或者false
六、抽象
背景:父类中会有一类方法,作用只是为了给子类提供可以重写的模板,本身操作没有任何意义,这时,我们只是希望父类只要存在这个方法的定义即可,不需要方法里边的操作内容。
当你无法确定该方法具体实现,那么就可以把该方法定义为抽象方法.
抽象方法语法规则:
abstract [访问修饰符] 返回值 方法名([参数列表]);一个类中如果有抽象方法,那么该类一定是一个抽象类. 抽象类的语法规则: abstract class 类名{ [abstract [访问修饰符] 返回值 方法名([参数列表]); ] [访问修饰符] 返回值 方法名([参数列表]){ //方法体 } }
抽象类的作用
定义类的模板,就是子类去重写实现方法.
注意:- 抽象方法没有方法体.
2.一个普通子类去继承一个抽象类,那么该类,实现抽象类中所有抽象方法.
3.抽象类不能被实例化,但是可以有构造器
4.抽象类不被分配内存
补充:final 修饰符: 最终的,不可改变的
变量: 改变量成常量,一旦赋值不能被改变.
局部变量: 定义赋值赋值
成员变量:定义赋值赋值,或者再构造器中赋值
方法:该方法是最终的方法,不能被重写
类:最终的类,不能有子类
注意:若父类中有final方法,不能被子类重写只能被子类继承或者子类重载。 - 抽象方法没有方法体.