多态
定义:某一类事物的多种存在形态,也可以理解为事物存在的多种体现形态。
体现:父类引用或者接口的引用指向了自己的子类对象。例如:Animal a = new Cat();动物是猫具体事物中抽取出来的父类型。这就是父类型引用指向了子类对象。父类的引用也可以接受自己的子类对象。
前提:必须是类与类之间有关系,要么是继承,要么就是实现。通常还有一个,就是覆盖。
好处:提高了程序的扩展性。
弊端:当父类引用指向子类对象时,虽然提高了扩展性,但只能访问父类中具备的方法,不可以访问子类中特有的方法。(也就是前期不能使用后期产生的功能,即访问的局限性)
多态的出现思想上也做着变化:以前是创建对象并指挥对象做事情。有了多态以后,我们可以找到对象的共性类型,直接操作共性类型做事情即可,这样可以指挥一批对象做事情,即通过操作父类或接口实现。
如何使用子类特有方法?
Animal a = new Cat();//这称为类型提升,也叫向上转型。
如果想要调用Cat的特有方法时,如何操作?
强制将父类的引用转成子类类型。也就是向下转型。
转换格式:父类 x = new 子类(); //向上转型 子类 y =(子类)x;//向下转型
规律:多态自始自终都是子类对象在做着变化。
引用数据类型的判断
判断某一类型引用指向的对象到底符合什么类型的时候用关键字instanceof
例子:if(a instanceof Cat)
instanceof:用于判断对象的类型。
格式:<对象 instanceof 类型(类类型或接口类型)>,判断一个对象是否所属于指定的类型。
Student instanceof Person = true;//student继承了person类
多态核心思想:我们对类型进行抽取,导致多态的产生,操作同一个的大类型对大类型中的所有小类型都能进行操作。 因为这个思想才提高了扩展性。
多态在子父类中的成员上体现的特点:
1.成员变量:在多态中,子父类成员变量同名。
编译时期:参考是引用型变量所属的类中是否有调用的成员。(编译时不产生对象,只是检查语法是否错误)
运行时期:也是参考引用型变量所属的类中是否有调用的成员。
简单来说:成员变量在编译运行都看左边。
2.成员函数
编译时期:参考引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
运行时期:参考对象所属的类中是否有调用的方法。
那么这是为什么呢?
因为在子父类中,对于一模一样的成员函数,有一个特性,就是覆盖。
简单来说:成员函数在多态调用时编译看左边,运行看右边。
3.静态函数
编译时期:参考的是引用型变量所属的类中是否有调用的成员。
运行时期:也是参考引用型变量所属的类中是否有调用的成员。
那么这是为什么呢?
因为静态方法其实不属于对象,而是所属于该方法所在的类。
调用静态的方法引用是哪个类的引用调用的就是哪个类中的静态方法。
简单来说:静态函数在多态调用时编译运行都看左边。
abstract(抽象类)
当多个类中出现相同功能,但功能主体不同。这个时候我们可以进行向上抽取,我们抽取的只是功能定义,而不是功能主体。
什么是抽象呢?
抽象就是笼统的、模糊的、不具体的,也可以说看不懂的东西就是抽象的东西。简单来说看不懂的方法就是抽象的方法。
什么时候需要声明为抽象方法呢?
在不断抽取过程中,我们将共性内容中的方法声明抽取,但是方法不一样,没有抽取,所以这时抽取到的方法,并不具体,需要被指定关键字abstract所标示,声明为抽象方法。
记住:抽象方法所在的类一定要标示为抽象类,也就是说该类需要被abstract关键字所修饰。
抽象类的特点:
1.抽象方法只能定义在抽象类中,抽象类和抽象方法都必须被abstract关键字修饰(可以描述类和方法,不可以描述变量)。
2.抽象方法只定义方法声明,并不定义方法实现。
3.抽象类不可以被创建对象(实例化),也就是说抽象类不可以用new创建对象,因为调用抽象方法是没有意义的。
4.抽象类中的方法要想被使用,必须由子类复写所有的抽象方法,建立子类对象调用。如果子类只覆盖了部分抽象方法,那么该子类也是一个抽象类。
注意:只有通过子类继承抽象类并覆盖了抽象类中所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。
抽象类中是否有构造函数?
有,用于给子类对象进行初始化。
抽象类中是否可以定义非抽象方法?
可以。其实抽象类和一般类是没有太大区别的,都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。所以抽象类和一般类在定义上都需要定义属性和行为的。只不过比一般类多了一个抽象函数。而且比一般类少了一个创建对象的部分。
抽象关键字abstract和哪些不可以共存?
final、private、static
抽象类中可不可以不定义抽象方法?
可以。抽象方法目的仅仅为了不让该类创建对象。
接口(interface)
初期理解,可以认为接口是一个特殊的抽象类,在英文里的所属关系是“like a”。
当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。
接口定义时,格式特点:
1.接口中常见定义:全局常量,抽象方法。
2.接口中的成员都有固定修饰符。
常量:public static final
方法:public abstract
注意:定义的常量中static和final都可以省略不写,方法中的public abstract也可以省略。当你省略后系统会自动把这些给你加上,但是最好还是写上,这样可以让阅读性更强一些。 还要记住,接口中的成员都是public的。
3.接口中有抽象方法,说明接口不可以实例化。接口的子类必须实现了接口中所有的抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。
4.类与类之间存在继承关系,类与接口之间存在的是实现关系。继承用extends 实现用implements
接口的特点:
1.接口是对外暴露的规则,也就是对外提供的规则。
2.接口是程序的功能扩展。如:可以理解为主板上提供的接口。
3.接口可以用来多实现,这是类与接口不一样的地方,也就是多继承改良后的结果。java将多继承机制通过多实现来体现。
4.类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
5.接口与接口之间可以有继承关系。
6.主要特点是降低了耦合性。
为什么要定义接口?
在需要扩展功能的时候就定义接口。如:电脑硬件要升级的时候。
接口给我们带来了什么好处呢?
接口提高了功能的扩展性和降低了耦合性。
继承与实现的区别:
简单的说:
1,类与类之间会存在继承关系。
2,类与接口之间,接口与接口之间会存在实现关系。
3,JAVA支持单继承和多实现。
4,继承指子类继承父类中已经有的方法,相同的方法将会子类覆盖父类的方法;实现指接口中定义的方法名却没有具体的方法体,需要自己去写。
继承:必须是类与类之间有所属关系才可以继承。关键字extends
继承:是子类和父类 可以看出继承只能是单继承的 就是只能有一个父类 他们是有上下关系的 子类继承父类后可以获得父类中所用的方法。
继承提高了代码的复用性,它把共有的数据提取出来,子类只需要继承就可以了
实现:实现是接口,类与接口是实现关系关键字implements
接口可以实现多实现,即一个类可以实现多个接口。所以接口的好处是提高了功能的扩展性和降低了耦合性.
接口里只定义了功能,而没有方法的实现,实现需要别的类去实现,功能里的内容需要你自己去写。而继承父类已经把功能实现了 你继承了它就可以直接使了 你要是不一样只能覆盖。
抽象类与接口:抽象类:一般用于描述一个体系单元,将一组共性内容进行抽取,特点:可以在类中定义抽象内容让子类实现,可以定义非抽象内容让子类直接使用。它里面定义的都是一些体系中的基本内容。
接口:一般用于定义对象的扩展功能,是在继承之外还需这个对象具备的一些功能。
抽象类和接口的共性:都是不断向上抽取的结果。
抽象类与接口的区别:
1.抽象类只能被继承,而且只能单继承。
接口需要被实现,还可以被多实现。
2.抽象类中可以定义非抽象方法,子类可以直接继承使用。
接口中都是抽象方法,都需要子类去实现。
3.抽象类使用的是 is a关系。
接口中使用的是like a关系。
4.抽象类的成员修饰符可以自定义。
接口中的成员修饰符是固定的。都必须是public的。
接口是怎样降低耦合性的呢?
例:在开发之前,先定义规则,A和B分别开发,A负责实现这个规则,B负责使用这个规则。至于A是如何对规则具体实现的,B是不需要知道的。这样这个接口的出现就降低了A和B直接耦合性。