一、 继承(extends)
继承的好处:提高了代码的复用性,让类与类之间产生了关系,有了这个关系才有了多特的特性
号外:千万不要为了获取其他类的功能而去继承,必须是有类与类之间有所属关系(is a)才可以继承
如何判断类之间是否有继承关系呢?如果不确定的话,就继承一下,判断一下是否是父类当中的所有元素都应该是子类应该有的。如果父类中有的元素不是子类的话,那么,就不应该有继承。
java中只支持单继承不直接支持多继承,因为多继承容易带来安全隐患,当多个父类都定义了相同功能时,所以不确定运行哪一个,但java保留了这种机制,因为多继承可以让子类获得更多的功能,并用另一种形式来表示那就是多实现,后面会讲到,
super关键字:
如果想访问父类就用super,super是父类的引用
如果子父类中出现了非私有的同名成员变量时,子类要访问本类中的变量就用this,要访问父类的就用super,两个关键字的用法几乎一致
覆盖:当子父类中出现一模一样的函数时,当子类对象调用该函数时,会运行子类函数的内容,就如同父类的函数被覆盖一样,也叫重写
当子类继承了父类,沿袭了父类的功能到子类中,但是子类虽有该功能,但是功能的内容却和父类不一样,这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义并重写功能内容
覆盖注意事项:
1、 子类覆盖父类,必须保证子类的权限大于等于父类权限,但如果父类是private时,子类可以继承但是不可以覆盖的
2、 静态只能覆盖静态
号外:
重载:只看同名函数的参数列表。
重写:子父类方法要一模一样,
子父类的构造函数的特点:
特点:在对子类对象进行初始化时,父类的构造函数也会运行那是因为子类的构造函数默认第一行有一条隐式的语句super();他会访问父类中的空参数列表的构造函数,而且子类中所有构造函数默认第一行都是super()
为什么子类一定要访问父类的构造函数呢?因为父类的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的所以,子类在对象初始化时,要先访问一下父类的构造函数,如果要访问父类中指定的构造函数可以通过手动定义super语句的方式指定
号外:super一定要放在子类构造函数的第一行
子类的实例化过程:
结论:子类的所有构造函数默认都会访问父类中空参数的构造函数;因为子类的每一个构造函数内都有一句隐式的super()。当父类中没有空参数的构造函数时,子类必须手动通过super或者this语句形式来指定要访问的构造函数。当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。
final关键字:
1、 可以修饰类、变量、函数
2、 被final修饰的类不可以被继承
3、 被final修饰的变量是一个常量,只能被赋值一次
4、 被final修饰的函数不可以被覆盖
当在描述事物时,一些数据的出现,值是固定的。那么这时为了增强阅读性,都给这些值起个名字。方便阅读。而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所有字母都大写,如果多个单词组成,单词通过(_)下划线连接。
抽象类(abstract):
当多个类中出现相同功能,但是功能主体不同,这时可以向上抽取,这时只抽取功能定义,而不抽取功能主体
面对抽象的事物虽然不具体,但是可以简单化,不用面对具体的事物
抽象类的特点:
1、 抽象方法一定定义在抽象类当中
2、 抽象方法和抽象类都必须被abstract关键字所修饰
3、 抽象类不可以用new创建对象,因为调用抽象方法没意义。
4、 抽象类中的抽象方法要被使用,必须由子类覆写其所有的抽象方法后,建立子类对象调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
四个问题:
1、 抽象类中一定有构造函数吗?
有,抽象类的构造函数虽然不能给抽象类实例化,因为抽象类不能new对象,但是抽象类有子类,可以给子类对象进行初始化
2、 抽象类一定是父类吗?
是的,因为子类必须复写抽象类中的方法才可以实例化,不然的话子类也还是一个抽象类4
3、 抽象类中可以不定义抽象方法吗?
可以的,有时可能接口里面有很多的抽象方法,但是子类只需要其中的某个方法,而这时却需要将接口中的所有方法都要覆盖后才可以使用,这样,代码的复用性就非常的低,这时我们就可以定义一个类,让类去实现接口,并将其中所有抽象方法覆盖,而这时的类里面的方法是没有意义的,所以就可以把这个类抽象(这时就产生了一个没有抽象方法的抽象类)这时再让子类继承抽象类就哦了,子类只需要覆盖抽象类中自己需要的方法即可。
4、 抽象关键字abstract和那些关键字不能共存?
① final,final修饰的函数不能被覆盖,所以。。
② private,子类不能直接访问被私有的函数,所以无法覆盖
③ static,抽象方法被类名调用没有意义,因为没有方法主体
抽象类和一般类的区别:
① 相同:都是对事物的属性和行为进行描述
② 不同的是抽象类描述的事物不具体,一般类表述的事物具体
③ 代码的不同:抽象类中既可以有抽象方法,也可以有非抽象方法,被子类使用或覆盖使用,一般类中只有一般方法,一般方法可以实例化,抽象方法不可以实例化
接口(interface)
初期可以理解为一个特殊的抽象类,类与接口之间有implements(实现)
当抽象类中的方法都是抽象的,那么该类就可以通过接口的形式来表示
接口的特点:
1、 对外暴露了规则
2、 程序的功能拓展 、
3、 可以多实现
4、 类与接口之间是实现关系,而且一个类可以继承另一个类的同时实现多个接口
5、 接口与接口之间是继承关系
接口定义时,格式特点:
1、 接口中常见定义,常量,抽象方法
2、 接口中的成员都有固定的修饰符:
常量:public static final
方法:public abstract
号外:接口中的成员都是public的
接口是不可以创建对象的,因为有抽象方法,需要被子类实现,子类对接口的抽象方法全部覆盖后,子类才可以实例化,否则子类也是一个抽象类
类用于描述事物共性的基本功能,接口用于定义事物的额外功能
抽象类和接口的区别:
1、 子类与类是继承关系(is a ) 子类与接口是实现关系(like a )
2、 抽象类中可以定义抽象和非抽象方法,子类可以直接使用或者覆盖使用,接口中定义的都是抽象方法,必须实现覆盖才能使用
二、 多态
多态也就是事物存在的多种体现形态
1、 多态的体现:父类的引用指向了子类对象
2、 多态的前提:必须是类与类之间有继承或者实现的关系,还会存在覆盖
3、 多态的好处:大大的提高了程序的拓展性
4、 多态的弊端:虽提高了拓展性,但是只能使用父类的引用访问父类中的成员
5、 多态的应用
6、 多态中成员的调用
① 成员变量:简单的说就是无论编译或者运行都看等号左边就哦了。
② 成员函数:简单的说就是编译看左边,运行看右边。
③ 静态函数:简单的说就是编译运行都看左边
向上转型:
动物 a =new 狗();//向上转型
好处:隐藏子类型,提高了代码的拓展性
弊端:功能被限定了,只能使用父类的功能,不能使用子类特有的功能
什么时候用:当不需要子类功能通过提高拓展性就可以完成操作是就向 上转型
向下转型:
动物 a = new 狗();
狗 d = (狗)a ; //向下转型
好处:可以使用子类特有的功能
弊端:当向下转型时,有风险,容易发生ClasscastException,只要转换deep类型和对象不匹配就会发生,想要安全,就必须进行判断,这时就需要用到另外一个关键子就是instanceof 格式:对象 instanceof 类型
什么时候向下转型:需要使用子类类型特有的方法时,但一定要判断
无论是向上转型还是向下转型其实都是子类在扮演着角色的转换