java基础--多态与包
一 多态:可以理解为事物存在的多种形态
1> 多态的体现
父类的引用指向了自己的子类对象。
父类的引用也可以接收自己的子类对象。
2> 多态的前提: 必须是类与类之间有关系。要么继承,要么实现。
通常还有一个前提:存在覆盖。
3> 多态的好处:
多态的出现大大的提高程序的扩展性。
4> 多态的弊端:
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
5> 多态的应用
多态的扩展性代码体现:
abstract class Animal { //各种动物吃的方式不同,抽取方法 abstract void eat(); } class Cat extends Animal { public void eat() { System.out.println("吃鱼"); } public void catchMouse() { System.out.println("抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨头"); } public void kanJia() { System.out.println("看家"); } } class Pig extends Animal { public void eat() { System.out.println("饲料"); } public void gongDi() { System.out.println("拱地"); } } // ----------------------------------------- class DuoTaiDemo { public static void main(String[] args) { // Cat c = new Cat(); // c.eat(); // Dog d = new Dog(); // d.eat(); // 没有使用多态时,需要根据参数的类型去调用相应的方法 /* Cat c1 = new Cat(); function(c1); function(new Dog()); function(new Pig()); */ // 父类的引用指向了自己的子类对象。 Animal c = new Cat(); c.eat(); function(new Cat()); function(new Dog()); function(new Pig()); } // 父类的引用也可以接收自己的子类对象。 // 多态的出现大大的提高程序的扩展性,后期只要传入动物,就可以 public static void function(Animal a)// Animal a = new Cat(); { a.eat(); // 不同动物已经并复写了eat方法 // a.catchMouse(); //提高了扩展性,但是只能使用父类的引用访问父类中的成员。 }
二 类型转换:
只有当转换的父类引用指向自己的子类对象时,该引用可以被提升。
向上转型 Animal a= new Cat();
向下转型Cat c =(Cat)a;
多态自始至终都是子类对象在做着变化
当想使用子类的特有方法时,需要向下转型。
注意:
Animal a = new Animal();
Cat c = (Cat)a; 将父类对象转成子类类型,是不可能的,难道只要是动物就能转成猫么?
转型示例:
abstract class Animal{ public abstract void eat(); } class Cat extends Animal { public void eat() { System.out.println("吃鱼"); } public void catchMouse() { System.out.println("抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨头"); } public void kanJia() { System.out.println("看家"); } } class Pig extends Animal { public void eat() { System.out.println("饲料"); } public void gongDi() { System.out.println("拱地"); } } // ----------------------------------------- class DuoTaiDemo2 { public static void main(String[] args) { // Animal a = new Cat();//类型提升,向上转型。 // a.eat(); // 强制将父类的引用。转成子类类型,向下转型。 //Cat c = (Cat)a; // c.catchMouse(); /*我们能转换的是父类应用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。 多态自始至终都是子类对象在做着变化。 下面代码将父类对象转成子类类型,是不可能的,难道只要是动物就能转成猫么? Animal a = new Animal(); Cat c = (Cat)a; */ function(new Dog()); function(new Cat()); } public static void function(Animal a)// Animal a = new Cat(); { a.eat(); if (a instanceof Cat) { Cat c = (Cat) a; c.catchMouse(); } else if (a instanceof Dog) { Dog c = (Dog) a; c.kanJia(); } /* * instanceof : 用于判断对象的类型。 对象 intanceof 类型(类类型 接口类型) */ } }
多态应用:主板与扩展设备的示例
package cn.xushuai.Test; /*沒有使用接口的情況,每次有新设备都需要定义独立的设备, class MainBoard{ public void run(){ System.out.println("mainboard run"); } public void useNetCard(NetCard c){ c.open(); c.close(); } } class NetCard{ public void open(){ System.out.println("netcard open"); } public void close(){ System.out.println("netcard close"); } } */ //各种设备的使用规则,只需扩展设备去遵循,实现方法即可,提高了程序的扩展性。 interface PCI { public void open(); public abstract void run(); } class MainBoard { public void userPCI(PCI p) { if (p != null) { // 防止空指针异常,检测是否有设备 p.open(); p.run(); } } } class NetCard implements PCI { public void open() { System.out.println("网卡 打开正常!"); } public void run() { System.out.println("网卡 开始 run.......!"); } } class SoundCard implements PCI { @Override public void open() { System.out.println("声卡 打开正常"); } @Override public void run() { System.out.println("声卡 开始 run.........!"); } } public class MainBoardDemo { public static void main(String[] args) { // TODO Auto-generated method stub MainBoard mb = new MainBoard(); mb.userPCI(new SoundCard()); mb.userPCI(new NetCard()); } }
三. 多态中(父类引用指向子类对象)成员的特点
1 非静态成员函数的特点:(因为存在覆盖)
1> 在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有,编译失败。
2> 在运行时期:参阅对象所属的类中是否有调用的方法。
(动态绑定:this所指对象去调用方法)
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
2. 成员变量的特点:无论编译和运行,都参考左边(引用型变量所属的类)。
3. 静态成员函数的特点:无论编译和运行,都参考做左边。
(静态绑定:静态方法一进内存就绑定在其所属类上了,所属于类)
原因:静态方法不需要对象,其决定于引用变量的所属类,所以一般不会覆盖静态方法。
四 Object 和Class类
1> Object:是所有对象的直接后者间接父类,传说中的上帝。
该类中定义的肯定是所有对象都具备的功能。
2> Object类中已经提供了对对象是否相同的比较方法。
如果自定义类中也有比较相同的功能,没有必要重新定义。
只要沿袭父类中的功能,建立自己特有比较内容即可。这就是覆盖。
3> new A对象时会加载A.class文件,class文件中有文件名A,构造函数,和一些 方法,是这一类对象的共性,
所以用Class类来描述这一类对象(类文件对象)。
五 包
对类文件进行分类管理,给类提供多层命名空间
写在程序文件的第一行
类名的全称是: 包名.类名
包也是一种封装形式
1. 为了简化类名的书写,使用一个关键字:import.i,mport 导入的是包中的类。
2. 建议,不要写通配符 * ,需要用到包中的哪个类,就导入哪个类。
3. 建立定包名不要重复,可以使用url来完成定义,url是唯一的
4. 包访问权限总结:
1> 包与包之间进行访问,被访问的包中的类以及类中的成员,需要public修饰。
2> 不同包中的子类还可以直接访问父类中被protected权限修饰的成员。
3> 包与包之间可以使用的权限只有两种,public protected。
5. 包访问权限图示
作用域 当前类 同一package 子孙类 其他package
public √ √ √ √
protected √ √ √ ×
friendly √ √ × ×
private √ × × ×
---------------------- android培训------- android培训、java培训、期待与您交流!
---------