------- android培训、java培训、java学习型技术博客期待与您交流! ----------
多态
1、接口(interface)
定义:是抽象方法和常量值的集合;
格式:interface 类名{}
接口中的成员修饰符是固定的:
成员常量:public static final
接口里面定义变量是全局常量,而且上面三个关键字都可以省略,而且只能是 public static final
成员函数:public abstract
接口里面定义的方法都是抽象的,而且上面的两个关键字也是可以省略的
接口中的成员都是public的
从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。
接口的出现将“多继承”通过另一种形式体现出来,即“多实现”。通过implements实现接口;
举例:interface Demo {
public static final int id = 1;
public abstract void start();
public abstract void run();
public abstract void stop();
}
特点:接口是对外暴露的规则;
接口是程序的功能扩展;
接口可以用来多实现;
接口的出现降低耦合性(实现了模块化开发,定义好规则,每个人实现自己的模块,大大提高了开发效率);
类与接口之间是实现关系,而且类可以继承一个类的同时,可以实现多个相互之间没有关系的接口;
多个无关的类可以实现同一个接口;
接口与接口之间可以有继承关系;
接口与实现类之间存在多态性,与继承关系类似;
用法:我们可以定义一个类来实现接口,使用implements关键字;
实现一个接口需要实现接口中所有的方法,抽象类除外;
可以使用匿名内部类来实现一个接口;
接口可以继承接口,使用extends关键字。 接口不能继承抽象类,因为抽象类中可能有不抽象的方法;
2、继承和实现:
类与类之间称为继承:
类无论是抽象还是非抽象,内部都可以定义非抽象方法,这个方法可以直接被子类继承使用。
类与接口是实现关系:
因为接口中的方法都是抽象的,必须由子类实现才可以实例化,所以就用了这个关键字implements
接口与接口之间是继承关系:
一个接口可以继承另一个接口,并添加新的属性和抽象方法,并且接口可以多继承
单继承和多实现:
类只能单继承,而接口可以多实现;
java将多继承机制进行改良,通过多实现接口的形式来体现
为什么不支持多继承呢?
因为继承的多个父类中定义了相同的方法,而方法内容不同,jvm无法判断选择哪个父类的方法,有安全隐患
而多实现就没有这个问题,既是是多个接口中都有相同的方法,但是他们都没有方法体
多实现的好处:
一个类继承另一个类的同时可以实现多个接口,多实现的好处是扩展了功能
接口的出现打破了单继承的局限性;
3、接口和抽象类:
共性:都是不断抽取出来的抽象的概念;
区别:抽象类体现继承关系,一个类只能单继承。接口体现实现关系,一个类可以多实现;
抽象类是继承用extends,是 "is a "关系。接口是实现用implements,是 "like a"关系;
抽象类中定义体系中的基本共性功能。接口通常定义体系中对象的扩展功能;
抽象类中可以定义非抽象方法,供子类直接使用。接口中都是抽象方法;
抽象类中的变量和方法没有默认修饰符,接口中的变量默认public static final,方法默认为public abstract;
4、多态(polymorphic)
某类事物存在多种形态。 在面向对象语言中,我们可以将函数的形参定义为一个父类类型,而在真正调用该函数时这
个父类类型的子类对象都可以传入,根据传入的子类对象不同,函数可以运行多种形态。
多态的特点:
成员函数:在编译时要查看引用变量所属的类中是否有所调用的方法;
在运行时要查看对象所属的类中是否有所调用的方法;
编译看左边运行看右边
成员变量:只看引用变量所属的类;
编译和运行都看等号左边;
静态函数:只看引用变量所属的类;
编译和运行都看等号左边;
应用程序不必为每一个子类编写功能调用,只需要对父类进行处理即可,可以大大提高程序的可复用性。
子类的功能可以被父类的变量调用,这叫向后兼容,可以提高程序的可扩充性和可维护性。
判断对象是否属于该类型通过一个关键字来完成instanceof : 对象 instanceof 类型
用于判断该对象是否所属于该类型;
体现:父类或者接口的引用指向或者接收自己的子类对象;
作用:多态的存在提高了程序的扩展性和后期可维护性
前提:父类引用指向子类对象;需要存在继承或者实现关系;要有覆盖操作(重写);
弊端:父类调用的时候只能调用父类里的方法,不能调用子类的方法,因为不知道将来会有什么样的子类继承父类;
实例
abstract class Animal { abstract void eat(); } class Activities { void doActivity(Animal a) { if (a != null) { a.eat(); } if (a instanceof Cat) { ((Cat) a).catchMouse(); } else if (a instanceof Dog) { ((Dog) a).kanJia(); } else if (a instanceof Pig) { ((Pig) a).sleep(); } } } class Cat extends Animal { @Override void eat() { System.out.println("吃鱼"); } void catchMouse() { System.out.println("抓老鼠"); } } class Dog extends Animal { @Override void eat() { System.out.println("吃骨头"); } void kanJia() { System.out.println("看家"); } } class Pig extends Animal { @Override void eat() { System.out.println("吃饲料"); } void sleep() { System.out.println("老是睡觉"); } } public class DuoTaiDemo1 { public static void main(String[] args) { // new Activities().doActivity(null); Animal a = new Cat();//类型提升,向上转型 a.eat(); //如果想要调用猫的特有方法,如何操作?? //强制将父类的应用转成子类类型,向下转型 Cat c = (Cat)a; c.catchMouse(); /** * 注意:前往不能将父类对象转成子类类型 * Animal a = new Animal(); * Cat c = (Cat)a; * 我们能转换的是父类引用执行了自己子类对象是,该应用可以被提升 * 多态自始至终都是子类对象在做着变化 */ //下面代码是利用Activities类创建对象完成对Cat,Dog,Pig进行的活动 new Activities().doActivity(new Cat()); new Activities().doActivity(new Dog()); new Activities().doActivity(new Pig()); } }
5、内部类(Inner Class)
在类里面定义的类称之为内部类(内置类、嵌套类)。内部类是外部类的一个成员,内部类的出现再次打破了java
单继承的局限性。 创建内部类对象时必须先创建一个外部类对象,通过一个外部类对象才能创建内部类对象;
外部类名.内部类名 变量名 = new 外部类名().new 内部类名();
内部类的class文件名为:外部类名$内部类名.class
访问特点:
内部类可以直接访问外部类中成员,包括私有成员,因为在使用内部类时一定有外部类对象,且只对应一个;
外部类名.this.成员名
而外部类要访问内部类中的成员必须要建立内部类的对象;因为在使用外部类时有可能还没有创建内部类对象
即使创建了,一个外部类对象也可能对应多个内部类对象
局部内部类:
定义在方法中的类,只能在方法中使用,而且使用的代码只能在声明的代码下面;
局部内部类只能在该内部类的方法内实例化,不可以在此方法外对其实例化;
局部内部类不能定义静态成员。需创建外部类对象才能使用,static不创建对象就能使用,这是矛盾的;
可以直接访问外部类中的成员;同时可以访问所在局部中的局部变量,但必须是被final修饰的;
因为方法的局部变量位于栈上,方法运行之后生命周期结束,不能再被访问,局部变量成为历史。
但是该方法结束之后,在方法内创建的内部类对象可能仍然存在于堆中!例如,对它的引用被传递
到其它某些代码,并存储在一个成员变量内, 那么方法结束之后还能访问这个对象。这时变量被销毁了,
对象还在,如果在对象的某个方法内访问这个变量就访问不到了。用final修饰这个变量后,变量
会一直存储在内存中,方法运行结束之后不被销毁;
成员内部类:
定义在成员位置上的内部类,在类中方法外;
创建对象方式:外部类名.内部类名 对象名 = 外部类对象.内部类对象
当内部类中定义了静态成员,该内部类必须是static的。
当外部类中的静态方法访问内部类时,内部类也必须是static的。
成员内部类之所以可以直接访问外部类的成员,是因为内部类中都持有一个外部类对象的引用:外部类名.this
可用的修饰符有:final、abstract、public、private、protected和static等
静态内部类:
可以使用static修饰一个类中的成员内部类;在类中方法外;
静态内部类不用创建外部类对象就可以直接创建对象:外部类名.内部类名 变量名 = new 外部类名.内部类名();
静态内部类可以定义静态成员:因为静态内部类可以直接使用,无需创建外部类对象。
静态内部类中不能访问外部非静态成员:因为创建静态内部类不需要外部类对象,也就是有可能没有创建外部类对象,
使用外部类非静态成员必须有外部类对象;
匿名内部类:就是内部类的简化写法
前提:内部类可以继承或实现一个外部类或者接口;
格式:new 外部类名或者接口名(){覆盖类或者接口中的代码(也可以自定义内容)}
先创建一个外部类或接口的子类,然后根据这个类或接口创建一个对象;
建立匿名内部类的关键点是重写父类的一个或多个方法,而不是创建新的方法:
因为用父类的引用不可能调用父类本身没有的方法,创建新的方法是多余的;
匿名内部类的使用:
通常在使用方法是接口类型参数,并该接口中的方法不超过三个时,可以将匿名内部类作为参数传递;
简化书写,如果阅读实在费劲的话,可以写有名字的内部类;
------- android培训、java培训、java学习型技术博客期待与您交流! ----------