Java基础之接口和多态知识点总结

来源:互联网 发布:足球经理ol停运 知乎 编辑:程序博客网 时间:2024/06/05 14:10
接口
当抽象类的方法都是抽象的时候,这时可以把该类定义成接口的形式。你可以先期将接口理解为特殊的抽象类。Eg.接口特点:   1,接口的方法都是抽象的。   2,接口不可以被实例化。   3,只有子类实现了接口中的所有抽象方法后,该子类才可以实例化,否则该类还是一个抽象类。格式特点当定义接口时,接口中的常见的成员有两种:   1,全局常量。   2,抽象方法。而且接口中的成员都有固定的修饰符:    全局常量:public static final     成员方法:public abstract这修饰即使不写,系统也会自动加上。建立一定书写,因为可以提高程序的阅读性。你会发现,接口中定义的成员都有一个共同的特点:都是public权限的。继承和实现的一点小区别:类与类之间称为继承:因为该类无论是抽象的还是非抽象的,它内部可以定义非抽象方法,这个方法可以直接被子类使用,所以子类继承就可以应用了。类与接口是实现关系:因为接口中的方法全都是抽象的,必须由子类实现完才可以实例化。所以就用了更确切的关键字:implements来表示
例子1.接口的引例实例演示。
[java] view plain copy
  1. package cn.itheima.day16;  
  2. /** 
  3.  * 先前可以把接口理解为特殊的抽象类。 
  4.  * 例如下面的代码: 
  5.  * interface Inter{ 
  6.  *    public static final int num = 4; 
  7.  *    public abstract void show(); 
  8.  * } 
  9.  * 接口-------->抽象类 
  10.  * abstract class AbsDemo{ 
  11.  *    abstract void show(); 
  12.  *    abstract void method(); 
  13.  * } 
  14.  */  
  15. //定义一个接口  
  16. interface Inter{  
  17.     public static final int num = 6;  
  18.     public abstract void show();  
  19.     public abstract void method();  
  20. }  
  21. /** 
  22.  * 如果要使用接口中的方法,必须定义一个类实现接口中的所有的抽象 
  23.  * 方法后,该子类才可以建立对象,并调用这些方法。 
  24.  * @author wl-pc 
  25. */  
  26. //实现接口  
  27. class InterImpl implements Inter{  
  28.     @Override  
  29.     public void show() {  
  30.         System.out.println("show run");  
  31.     }  
  32.     @Override  
  33.     public void method() {  
  34.         System.out.println("method run");  
  35.     }  
  36. }  
  37. public class InterfaceDemo {  
  38.     public static void main(String[] args) {  
  39.         InterImpl i = new InterImpl();  
  40.         i.show();  
  41.         i.method();  
  42.         System.out.println(Inter.num);  
  43.         System.out.println(InterImpl.num);  
  44.         System.out.println(i.num);  
  45.     }  
  46. }  
类只能单继承,而接口可以被多实现。java将多继承机制进行改良,通过多实现接口的形式来体现。为什么不支持多继承呢?因为当多个父类中定义了相同方法,而方法内容不同是,子类对象在调用该方法时,不明确要运行哪一个,有安全隐患,也就是不确定性。而接口进行多实现就没有这个问题了,因为接口中的方法都没有主体。接口的另一个好处:一个类在继承另一个类的同时可以实现多个接口.接口的出现就避免了单继承的局限性。父类中定义的该对象的基本功能,而接口中定义的是该对象的扩展功能。

例子2.接口的多实现的实例演示。

[java] view plain copy
  1. package cn.itheima.day16;  
  2. class Demo{  
  3.     public void function(){  
  4.         System.out.println("function run");  
  5.     }  
  6. }  
  7. interface Inter1{  
  8.     void show();  
  9. }  
  10. interface Inter2{  
  11.     void show();  
  12. }  
  13. //多实现接口的演示  
  14. class DemoA implements Inter1,Inter2{  //接口可以多实现  
  15.     public void show(){  
  16.         System.out.println("多实现接口的DemoA run");  
  17.     }  
  18.     public void method(){  
  19.         System.out.println("method run");  
  20.     }  
  21. }  
  22. //继承类并实现接口的演示  
  23. class Test extends Demo implements Inter1,Inter2{  
  24.     @Override  
  25.     public void show() {  
  26.         System.out.println("单继承和多实现接口的show run");  
  27.     }  
  28. }  
  29. public class InterfaceDemo2 {  
  30.     public static void main(String[] args) {  
  31.         DemoA d = new DemoA();  
  32.         d.show();  
  33.         d.method();  
  34.         Test test = new Test();  
  35.         test.show();  
  36.          t.function();  
  37.     }  
  38. }  
抽象类和接口的区别:    1.抽象类只能被单继承。      接口可以被多实现。    2.抽象类中可以定义非抽象方法,直接被子类使用。      接口中只有抽象方法,必须被子类实现后才可以被使用。    3.抽象类中定义体系中的基本共性功能。      接口中通常定义体系中对象的扩展功能。    4.接口的出现避免了单继承的局限性。    5.抽象类被继承,是 is a 关系: xx1是xx2中的一种。      接口可以被实现,是 like a关系:xx1像xx2 中的一种。
例子3:抽象类和接口的整合实例演示。
[java] view plain copy
  1. package cn.itheima.day16;  
  2. /** 
  3.  * 学员的例子 
  4.  * 抽烟的学员 
  5.  *  
  6.  * 老师 
  7.  * 抽烟的老师 
  8.  * @author wl-pc 
  9. */  
  10. /*发现抽烟的功能并不是体系中应该具备的基本功能。而是具体子类所具备的特有扩展 
  11.  * 功能。将这个功能抽取到一个接口中,这个是对对象的功能进行扩展*/  
  12. interface Smoking{  
  13.     public abstract void smoke();  
  14. }  
  15. //学员的抽象类  
  16. abstract class XueYuan{  
  17.     abstract void study();  
  18. }  
  19. class SmokeXueYuan extends XueYuan implements Smoking{  
  20.     @Override  
  21.     void study() {  
  22.         System.out.println("study");  
  23.     }  
  24.     @Override  
  25.     public void smoke() {  
  26.         System.out.println("Xueyua Smoke");  
  27.     }  
  28. }  
  29. //老师的抽象类  
  30. abstract class Teacher{  
  31.     abstract void teacher();  
  32. }  
  33. class SmokeTeacher extends Teacher implements Smoking{  
  34.     @Override  
  35.     void teacher() {  
  36.         System.out.println("teacher");  
  37.     }  
  38.     @Override  
  39.     public void smoke() {  
  40.         System.out.println("teacher smoke");  
  41.     }  
  42. }  
  43. public class InterfaceDemo3 {  
  44.     public static void main(String[] args) {  
  45.         SmokeXueYuan  xueYuan = new SmokeXueYuan();  
  46.         xueYuan.smoke();  
  47.         xueYuan.study();  
  48.         SmokeTeacher teacher = new SmokeTeacher();  
  49.         teacher.teacher();  
  50.         teacher.smoke();  
  51.     }  
  52. }  
  53. /* 改变问题领域(如下): 
  54.  * 分析烟民这个领域。  
  55.  * abstract class YanMin { 
  56.  *      abstract void smoke();  
  57.  *  } 
  58.  * 对于烟民而言,吸烟是主要功能,而学习是添加的功能。 
  59.  * interface Study {  
  60.  *      void study();  
  61.  * } 
  62.  * 烟民不一定都具有学习的功能,所以将学习功能定义为借口 
  63.  * class StudentYanMin extends YanMin implements Study { 
  64.  *     void smoke() { 
  65.  *          System.out.println("Student smoke");  
  66.  *     }  
  67.  *     public void study(){}  
  68.  * } 
  69.  */  
类与类之间是继承关系。
类与接口之间是实现关系。接口与接口之间继承关系,通过接口可以多继承。Java支持多继承,在类上,Java的多继承是不允许的,因为存在着不确定性。但是,在接口上可以存在多继承的。
例子4:接口的多实现的实例演示。
[java] view plain copy
  1. package cn.itheima.day16;  
  2. interface A{  
  3.     void a();  
  4. }  
  5. interface C{  
  6.     void c();  
  7. }  
  8. interface B extends A,C{  
  9.     void b();  
  10. }  
  11. class D implements B{  
  12.     @Override  
  13.     public void a() {  
  14.         System.out.println("a");  
  15.     }  
  16.     @Override  
  17.     public void c() {  
  18.         System.out.println("c");  
  19.     }  
  20.     @Override  
  21.     public void b() {  
  22.         System.out.println("b");  
  23.     }  
  24. }  
  25. /*class AA{} 
  26. class BB{} 
  27. //这种写法是错误的,因为类只支持单继承,不支持多继承 
  28. class CC extends AA,BB{ 
  29. }*/  
  30. public class InterfaceDemo4 {  
  31.     public static void main(String[] args) {  
  32.         D d = new D();  
  33.         d.a();  
  34.         d.c();  
  35.         d.b();  
  36.     }  
  37. }  
猫,狗:这些事物都称为动物。动物这种类型:有多种体现的形态。   一个具体的动物,具备多种体现类型。(猫:称为猫或动物)    猫这个具体对象,它既可以称之为猫,也可以称之为动物。    class 动物{    }    class 猫 extends 动物{    }    猫 x = new 猫();    动物 y = new 猫();    class 狗 extends 动物{    }    狗 x = new 狗();    动物 y = new 狗();    多态        1,在程序中的体现:父类引用或者接口引用指向了自己的子类对象。        2,好处:提高了代码的扩展性,后期的可维护性        3,前提            1)类与类之间必须有继承关系或者实现关系。            2)通常都需要进行覆盖。        4,弊端           进行多态应用时,前期并不知道后期会有多少个子类出现,但是可以使用父类的引用来调用父类的方法。而后期哪个子类对象出现就执行哪个子类的具体方法实现。这就是程序的扩展性。      但是,前期调用的时候,只能调用父类中的方法,而不能调用具体子类的特有方法。因为前期还不知道具体的子类是谁。多态的思想    以前:定义对象,并指挥对象做事情(调用对象方法)当对象多了以后,指挥动作就会变的很麻烦。这时重新思考这个问题。找到这些对象的共性类型。直接指挥这个共性类型做事情即可。这样凡是属于这个类型的个体都会执行。    比如:建立猫对象,调用猫的eat方法。建立狗对象调用eat方法。很麻烦。    找到猫和狗的共性类型:动物。只要指挥动物的eat方法。即可。这样猫和狗都会进行eat动作。

例子5:多态的演示程序。

[java] view plain copy
  1. package cn.itheima.day16;  
  2. abstract class Animal{  
  3.     abstract void eat();  
  4. }  
  5. class EatSomething{  
  6.     void startEat(Animal a){  
  7.         a.eat();  
  8.     }  
  9. }  
  10. class Cat extends Animal{  
  11.     void eat(){  
  12.         System.out.println("鱼");  
  13.     }  
  14.     void catchMouse(){  
  15.         System.out.println("做老鼠");  
  16.     }  
  17. }  
  18. class Dog extends Animal{  
  19.     @Override  
  20.     void eat() {  
  21.         System.out.println("骨头");  
  22.     }  
  23.     void looHome(){  
  24.         System.out.println("看家");  
  25.     }     
  26. }  
  27. public class DuoTaiDemo1 {  
  28.     public static void main(String[] args) {  
  29.         EatSomething es = new EatSomething();  
  30.         es.startEat(new Cat());  
  31.         es.startEat(new Dog());  
  32.     }  
  33. }  

在转型过程中,其实都是子类对象在做着变化。当你想使用子类的特有功能时,需要将父类型转成子类型才可以使用。
注意:必须保证,这个父类型指向的是该子类型的对象.例子6:多态中的对象的向上转型和向下转型的实例演示。

[java] view plain copy
  1. package cn.itheima.day16;  
  2. abstract class Animal1{  
  3.     abstract void eat();  
  4. }  
  5. class EatSomething1{  
  6.     void startEat(Animal1 a){  
  7.         a.eat();  
  8.     }  
  9. }  
  10. class Cat1 extends Animal1{  
  11.     void eat(){  
  12.         System.out.println("鱼");  
  13.     }  
  14.     void catchMouse(){  
  15.         System.out.println("做老鼠");  
  16.     }  
  17. }  
  18. class Dog1 extends Animal1{  
  19.     @Override  
  20.     void eat() {  
  21.         System.out.println("骨头");  
  22.     }  
  23.     void looHome(){  
  24.         System.out.println("看家");  
  25.     }     
  26. }  
  27. public class DuoTaiDemo2 {  
  28.     public static void main(String[] args) {  
  29.         Animal1 a = new Cat1(); //父类引用指向子类对象,子类对象提升为了父类型,向上转型。自动类型提升。  
  30.         a.eat();  
  31.         //c.catchMouse(); //编译错误  
  32.           
  33.         //注意:在转型过程中,至始至终都是子类对象在做着改变。  
  34.         //当你想使用子类的特有功能时,需要将父类型转成子类型才可以使用。  
  35.         //注意:必须保证,这个父类型指向的该子类型的对象。  
  36.         //想要使用猫的做老鼠的功能,强制类型转换,向下转型。  
  37.         Cat1 c = (Cat1)a;  
  38.         c.eat();  
  39.         c.catchMouse();        
  40.     }  
  41. }  

可以对传入的对象进行类型的判断。通过一个关键字来完成 instanceof : 对象instanceof 类型  
用于判断该对象是否所属于该类型。
例子7:判断对象类型是否属于指定的类型。
[java] view plain copy
  1. package cn.itheima.day16;  
  2. import java.lang.reflect.Method;  
  3.   
  4. abstract class Animal2{  
  5.     abstract void eat();  
  6. }  
  7. class EatSomething2{  
  8.     void startEat(Animal2 a){  
  9.         a.eat();  
  10.     }  
  11. }  
  12. class Cat2 extends Animal2{  
  13.     void eat(){  
  14.         System.out.println("鱼");  
  15.     }  
  16.     void catchMouse(){  
  17.         System.out.println("做老鼠");  
  18.     }  
  19. }  
  20. class Dog2 extends Animal2{  
  21.     @Override  
  22.     void eat() {  
  23.         System.out.println("骨头");  
  24.     }  
  25.     void looHome(){  
  26.         System.out.println("看家");  
  27.     }     
  28. }  
  29. public class DuoTaiDemo3 {  
  30.     public static void main(String[] args) {  
  31.         Method(new Dog2());  
  32.     }  
  33.     private static void Method(Animal2 a) {  
  34.         //可以对传入的对象进行类型的判断。  
  35.         //通过一个关键字来完成 instanceof : 对象 instanceof 类型  用于判断该对象是否所属于该类型。  
  36.         if(a instanceof Cat2){  
  37.             Cat2 c= (Cat2)a;  
  38.             c.eat();  
  39.             c.catchMouse();  
  40.         }else if(a instanceof Dog2){  
  41.             Dog2 d = new Dog2();  
  42.             d.eat();  
  43.             d.looHome();  
  44.         }else {  
  45.             a.eat();  
  46.         }  
  47.     }  
  48. }  
接口的基本思想:  举例说明:主板的例子。  接口的三个特性:     1.接口就是对外暴露的规则。     2.接口是功能的扩展。     3.接口的出现降低了耦合性(紧密联系程度降低),耦合性的降低就实现了模块化的开发,叫做开发前定义好规则,你在实现规则,我在使用规则,至于怎么实现的和我没关系。我只要知道这个规则即可。  面试回答:电脑的机箱                  电源插孔的例子                 笔记本的例子                 主板的例子例子8:主板运行和PCI结合的实例演示。
[java] view plain copy
  1. package cn.itheima.day16;  
  2. /** 
  3. * 需求:主板运行。为了提高主板的功能扩展。因为日后有可能会出现一些新的功能,比如音频,网络等等。 
  4. * 以后会出现什么样的功能,是不确定的。但是前期在设计的时候,可以对外提供一个规则。只要后期的 
  5. * 功能设备符合这个主板对外提供的规则即可被主板使用。就在主板上定义了PCI插槽。 这个插槽就是一个接口。 
  6. * 这个示例作为一个重点看一下 
  7.  * @author wl-pc 
  8.  */  
  9. /** 
  10.  * 接口的基本思想: 
  11.  * 举例说明:主板的例子。 
  12.  * 接口的三个特性: 
  13.  *    1.接口就是对外暴露的规则。 
  14.  *    2.接口是功能的扩展。 
  15.  *    3.接口的出现降低了耦合性(紧密联系程度降低),耦合性的降低就实现了模块化的开发, 叫做开发前定义好规则,你在实现规则,我在使用规则,至于怎么实现的和我没关系。我只要知道这个规则即可。 
  16.  * 面试回答:电脑的机箱 
  17.  *          电源插孔的例子 
  18.  *          笔记本的例子 
  19.  *          主板的例子 
  20.  */  
  21. interface PCI{  
  22.     public void open();  
  23.     public void close();  
  24. }  
  25. class MainBoard{  
  26.     public void run(){  
  27.         System.out.println("mainboard run");  
  28.     }  
  29.     /** 
  30.      * 主板还有一个功能,就是使用PCI插槽上的具体设备。 
  31.      * 只要定义PCI 接口的引用,用于接收符合该接口的设备即可。 
  32.      */  
  33.     public void usePCI(PCI p){  //p就是一个接口类型的应用,接口类型的引用需要指向其子类的对象。  
  34.         if(p!=null){  
  35.             p.open();  
  36.             p.close();  
  37.         }  
  38.     }  
  39. }  
  40. //定义网卡实现PCI接口  
  41. class NetCard implements PCI{  
  42.     @Override  
  43.     public void open() {  
  44.         System.out.println("netcard open");  
  45.     }  
  46.     @Override  
  47.     public void close() {  
  48.         System.out.println("netcard close");  
  49.     }  
  50. }  
  51. //定义声卡实现PCI接口  
  52. class SoundCard implements PCI{ //like a关系 :网卡很像一个PCI  
  53.     @Override  
  54.     public void open() {  
  55.         System.out.println("SoundCard open");  
  56.     }  
  57.     @Override  
  58.     public void close() {  
  59.         System.out.println("SoundCard close");  
  60.     }  
  61. }  
  62. public class PCIDemo {  
  63.     public static void main(String[] args) {  
  64.         MainBoard mb = new MainBoard();  
  65.         mb.run();  
  66.         mb.usePCI(new NetCard());  
  67.         mb.usePCI(new SoundCard());  
  68.     }  
  69. }  
例子9:数据库使用接口的实例演示。
[java] view plain copy
  1. interface SQLTool{  
  2.     add();  
  3.     delete();  
  4. }  
  5. class MySqlTool implements SQLTool{  
  6.     add(){  
  7.         1,连接mysql数据库。  
  8.         2,添加数据。  
  9.         3,关闭数据库。  
  10.     }  
  11.     delete(){  
  12.         1,连接mysql数据库。  
  13.         2,删除数据。  
  14.         3,关闭数据库。  
  15.     }  
  16. }  
  17. class OracleTool implements SQLTool{  
  18.     add(){  
  19.         1,连接Oracle数据库。  
  20.         2,添加数据。  
  21.         3,关闭数据库。  
  22.     }  
  23.     delete(){  
  24.         1,连接Oracle数据库。  
  25.         2,删除数据。  
  26.         3,关闭数据库。  
  27.     }  
  28. }  
  29. //定义一个工具类,返回指定的对象。  
  30. class Tool{ //静态工厂设计模式。  
  31.     public static SQLTool getInstance(String name){  
  32.         if(name.equals("mysql"))  
  33.             return new MySqlTool();  
  34.         if(name.equals("oracle))  
  35.             return new OracleTool();  
  36.     }  
  37. }  
  38. class SQLDemo{  
  39.     public static void main(String[] args){  
  40.          SQLTool t = Tool. getInstance(“mysql”);  
  41.           t.add();  
  42.           t.delete();  
  43.               
  44.           SQLTool t2 = Tool. getInstance(“oracle”);  
  45.           t2.add();  
  46.           t2.delete();  
  47.     }  
  48. }  
多态中的细节。在多态中:    成员变量       编译时期:看的引用型变量所属的类中是否有所调用的变量.       运行时期:也是看引用型变量所属的类是否有调用的变量。       简单一句话:成员变量,无论编译还是运行都看引用型变量所属的类。       更简单的话:成员变量,编译和运行都看等号 的左边。    成员函数       编译时期:看的引用型变量所属的类中是否有调用的方法。       运行时期:看的对象所属的类中是否有调用的方法,       如果父子出现同名方法,会运行子类中的方法。因为方法有覆盖特性。       简单说:对于成员函数,编译看左边,运行看右边。其实非静态函数,在内存有一个动态绑定机制。其实就是f指向了具体的子类对象。编译看到的f所属的Fu类中是否有这个方法。运行的时候f就绑定到了一个具体的子类对象上,子类对象运行时会覆盖父类中的相同方法,而运行子类的内容。    静态函数       编译时期:看的是引用型变量所属的类中是否有调用的方法。       运行时期:也是看的是引用型变量所属的类中是否有调用的方法。       简单说: 对于静态函数,编译看左边,运行也看左边.静态函数存放于每一个所属类的静态区中,它是被静态绑定,就是类一加载,就已经有固定所属的调用就是那个类名。整体总结    成员变量和静态成员:编译和运行都看左边。    只有非静态的成员函数:编译看左边,运行看右边。当定义功能时,该功能中有一部分功能是确定,一部分功能是不确定的。这时将不确定的部分通过一个函数暴露出去,延迟到子类去完成。这时我们发现解决这类功能部分明确部分不明确需求,用这个思想就可以很高效。这个思想就成了一个解决该类问题就有效的方案。起个名字就叫做:模版方法设计模式。
例子10:模版方法设计模式的实例演示。
[java] view plain copy
  1. package cn.itheima.day16;  
  2. import org.omg.IOP.Codec;  
  3. /* 
  4. 计算一个程序运行的时间。 
  5. 思路: 
  6. 在该程序运行之前记录一个时间。 
  7. 运行完在记录一个时间,相减即可. 
  8. 如何获取时间呢? 
  9. */  
  10. /* 
  11. 为了提高该功能的复用性,将该功能封装到对象中。只要以后使用时找到该对象即可。 
  12. 当定义功能时,该功能中有一部分功能是确定,一部分功能是不确定的。 
  13. 这是将不确定的部分通过一个函数暴露出去,延迟到子类去完成。 
  14. 这是我们发现解决这类功能部分明确部分不明确需求,用这个思想就可以很高效。 
  15. 这个思想就成了一个解决该类问题就有效的方案。起个名字就叫做:模版方法设计模式。 
  16. */  
  17. abstract class GetTime{  
  18.     public final void getTime(){  
  19.         long  start = System.currentTimeMillis();  
  20.         code();  
  21.         long  end = System.currentTimeMillis();  
  22.         System.out.println("毫秒="+(end-start));  
  23.     }  
  24.     public abstract void code();  
  25. }  
  26. class Sub extends GetTime{  
  27.     public void code(){  
  28.         for(int x=0; x<1000; x++){  
  29.             System.out.println("y");  
  30.         }  
  31.     }  
  32. }  
  33. public class TemplateDemo {  
  34.     public static void main(String[] args) {  
  35.         Sub sub = new Sub();  
  36.         sub.getTime();  
  37.     }  
  38. }  
原创粉丝点击