面向对象特征--多态
多态:同一种事物,在不同时刻表现不同的状态 多态存在的三个必要条件:1.要有继承(包括接口的实现)(前提条件)2.要有重写(前提条件)3. 父类引用指向子类对象
//1.当编译期类型是父类,运行期类型是子类时,被称为父类引用指向子类对像 class Animal{ ……} class Cat extends Animal{ ……} class Dog extends Animal { ……} Animal x = new Cat() //Animal 的引用指向Cat的对象 //2.多态环境下对成员方法的调用 lass Animal{ void show() { System.out.println("Anmial");}} class Cat extends Animal{ void show() { System.out.println("cat");} }……. Animal x = new Cat() x.show() //调用的是子类中的方法 //简单的说:编译看左边,运行看右边。 //3.多态环境下对静态成员方法的调用 class Animal{ int num = 3;} class Cat extends Animal { int num = 4; }……. Animal x = new Cat() x.num; //调用的是动物类中的成员变量。 //简单的说:编译和运行都看等号左边。 //注意:变量不存在被子类覆写这一说法,只有方法存在覆写。 //4.方法参数具有多态性 class Animal{ void eat() {}} class Cat extends Animal{ void eat() {}} class Dog extends Animal{ void eat(){}} //方法的形式参数类型是父类类型,而传递的实际参数可以是任意子类的对象 method(Animal animal){ animal .eat();} //方法参数多态性的好处:提高代码的扩展性 //5.向上转型 class Animal{ void eat(){}} class Cat extends Animal{ void look() { System.out.println("看家");} } ……… Animal x=new Cat() //向上造型,Cat对象提升到Animal对象 x.eat() //只能使用父类中的方法 x.look() //报错!不能使用子类中的方法 //向上转型的作用是:提高程序的扩展性。 //6.向下转型 class Animal{ void eat(){ }} class Cat extendsAnimal{ void look() { System.out.println("看家");} } ……… Animal x=new Cat() Cat m=(Cat)x; //向下转型 m.eat() ; m.look();//子父类中的方法都可以使用 //向下转型的作用是:为了使用子类中的特有方法。
public static void main(String[] args) { /* 多态: (同一个父类类型) , 父类可以表示任意的子类对象, 同一种事务,在不同时刻表现不同的状态. 实现多态条件: 要有继承,父类可以表示子类,他们之间是有关系的 要有重写(特指的抽象的方法), 重写过来后,调用的就是子类自己的方法实现 父类引用指向子类对象 */ Dog dog1 = new Dog(); Animal dog = new Dog(); dog.eat(); dog.sleep(); //编译期间看左边类,运行期间看右边 //编译期间 类型是父类类型,调用的是父类中定义的方法 Animal bird = new Bird(); bird.eat();//运行期间, 运行时指向的是具体的子类对象,运行时调用的是子类的方法 bird.sleep(); bird.show(); // 对于静态方法,编译和运行都看左边 System.out.println(bird.num);//对于成员变量, 编译和运行都看左边 }
/* 有什么好处:多态方式,扩展性强 非多态方式,扩展性不强,添加功能就需要修代码*/ public class Test3 { public static void main(String[] args) { byte x = 10;//1 127 int y = x;//4 long z = 100;//8 y = (int)z; // Test3 t = new Test3(); Animal dog = new Dog(); //向上转型 子类类型自动转为父类类型 Animal bird = new Bird(); Animal cat = new Cat(); t.feedAnimal(bird);//实际传入的是bird t.feedAnimal(dog);//实际传入的是dog t.feedAnimal(cat);//实际传入的是cat } /* 饲养员喂动物,动物吃东西 */ public void feedAnimal(Animal animal){ animal.eat(); //animal.play(); 多态不足: 父类类型不能访问子类中特有的方法 //解决办法,将父类类型,向下转为子类类型 // 引用 instanceof 具体的类型 判断引用实际类型是否为后面指定的具体类型 if(animal instanceof Bird){ Bird b = (Bird) animal; b.play(); } } } //Object valueOf(Object obj) Object可以用来实现多态性
final关键字
final 用于声明属性,方法和类。 1.属性:定义就必须直接赋值或者在构造方法中进行赋值,并且后期都不能修改。 2.方法:子类里不可以重写。 3.类:不能被定义为抽象类或是接口,不可被继承 final属性赋值 1.在声明时同时赋值,往往与static 一起使用。 2.声明时不赋值,必须在构造方法中逐一赋值。 3.总的原则:保证创建每一个对象的时候,final属性的值是确定的。
对参数做final修饰。在方法参数前面加final关键字,为了防止数据在方法体中被修改。
/* final修饰类, 属性,方法 修饰类: final修饰的类不能被其他类继承 例如String 修饰方法: final修饰的方法不能被子类重写 修饰属性: final修饰成员变量变为常量,值不可改变 */ public class FinalDemo{ //final修饰成员变量为常量,直接对其初始化赋值,建议使用static修饰 public final static int NUM = 10; //final修饰的成员变量为常量.在定义时没有为其初始化,必须在某个构造方法为其赋值,这样每个对象中都有一个常量 public final int count; public FinalDemo(){ this.count = 0; } public FinalDemo(int count) { this.count = count; } public final void demo(final int a){ //a=10; System.out.println("父类具体实现"); } public static void main(String[] args) { new FinalDemo(10); new FinalDemo(20); new String(); } }
接口
接口的定义:使用 interface 关键字用来声明一个接口。 [访问修饰符] interface 接口名称 [extends 其他的接口名1,….其他的接口名n]{// 声明常量 抽象方法 静态方法 默认方法} 接口的使用:类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。 [访问修饰符] class 类名 implements 接口名1,接口名2……{ } 结合继承:[访问修饰符] class 类名 extends 父类名 implements 接口名1,接口名2……{ } 接口的特性: 1.接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字 2.接口中方法可以是抽象的,静态的,默认的 3.接口中声明的属性默认为 public static final 的 4.接口不是被类继承了,而是要被类实现 5.接口不能实例化对象 6.与继承关系类似,接口与实现类之间存在多态性 7.一个接口能继承其它多个接口 8.当类实现接口的时候,类要实现接口中所有的抽象方法。否则,类必须声明为抽象的类
/* interface修饰的为接口 类继承接口(抽象类) 类只能直接继承一个类 类可以实现多个接口 接口可以继承多个接口 */ public interface MyInterface extends MyInterfaceA,MyInterfaceB,MyInterfaceC{ //接口中定义成员变量,默认是静态常量 public static final int num = 10; int count = 20; //接口中定义的无方法体的方法,默认抽象方法 public abstract void eat(); void sleep(); //jdk8之后添加静态方法,默认方法 public static void test(){ System.out.println("接口中的静态方法"); } //默认方法是由子类来使用的 public default void test1(){ System.out.println("接口中的默认方法"); } }