Java编程思想(9)接口
2018-01-20 23:34
267 查看
抽象类和抽象方法(abstract)
1、有些基类的方法往往是哑方法。实际上是无实际意义的。这些类的目的是为它所有导出类创建一个通用接口。2、创建一个这样的类对象没有意义,甚至还要阻挡使用者这样做。
3、Java提供一个叫做抽象方法的机制。这种方法不完整,仅声明而没有方法体,如下格式:
abstract void f();
用abstract关键字,且不包含f()的具体实现。
4、包含抽象方法的类叫做抽象类(只要有一个就是,虽然可能有其他方法不一定是抽象方法),该类被定义为抽象的。
5、编译器会阻止构建抽象类的对象。
6、从一个抽象类继承,并想创建新类的对象的话,必须为基类中所有的抽象方法提供方法定义。如果不这样做,那导出类也必须是abstract的。编译器这一关就过不了。
7、也可以创建一个没有任何抽象方法的抽象类,其目的是阻止创建这个类的任何对象。
接口(interface)
1、abstract关键字允许在类中创建一个或多个没有定义的方法,只有接口。这些方法实现由类的继承者创建。2、interface则产生一个完全抽象的类,没有实现任何一个方法。这样,任何使用某特定接口的代码都知道可以调用接口的那些方法。因此,接口可以用来建立类与类之间的协议。
3、把class替换成interface,就可完成定义。
interface Instrument{
void play(Note n);
void adjust();
}
4、要让一个类遵循某个特定接口(或一组接口),需要使用implements关键字。它表示本类将实现接口具体如何工作,且遵循这些接口的定义要求。
5、接口中方法缺省是public的,也必须是public的。
6、一个小例子。定义了Instrument接口,实现了Wind和Brass两个类,遵循这个接口。
package C_09; //这里定义了一个简单的枚举,用于其他地方引用。 public enum Note01 { C,D,E,F,G,A,B }
package C_09; import java.util.*; import C_09.Note01; interface Instrument{ void play(Note01 n); void adjust(); } class Wind implements Instrument{ public void play(Note01 n) { System.out.println(this +".play()"+n); } public void adjust() { System.out.println(this+".adjust()"); } } class Brass implements Instrument{ public void play(Note01 n) { System.out.println(this +".play()"+n); } public void adjust() { System.out.println(this+".adjust()"); } public String toString() {return "Brass"; } } public class Music5Interface01 { public static void main(String[] args) { Instrument[] orchestra = {new Wind(),new Brass()}; orchestra[0].play(Note01.B); orchestra[1].play(Note01.E); // TODO Auto-generated method stub } }结果为:
C_09.Wind@122bbb7.play()B
Brass.play()E
因为Brass实现了toSting()方法,打印好看点。
完全解耦
1、多重继承
1、接口没有任何具体实现,也就是说没有任何与接口相关的存储。因此,无法阻止多个接口的组合。2、如果从一个非接口类型继承,只能从一个类继承,其余的都是接口。将所有接口名都置于implements之后,用逗号隔开。可以继承任意多个接口,并可以向上转型成为每个接口,因为每个接口都是一个独立类型。
3、看以下例子:
package C_09; //第一个接口 interface CanFight{ void fight(); } //第二个接口 interface CanSwim{ void swim(); } //第三个接口 interface CanFly{ void fly(); } class ActionCharacter{ //这里的flight与上面CanFlight()没什么关系,同名 public void fight() {System.out.println("fight01");}; } class Hero extends ActionCharacter implements CanFight,CanSwim,CanFly{ //因为Hero继承自ActionCharacter,所以继承了它的flight()方法,所以天然完成了CanFlight接口的flight()方法。 //此处只需要实现另外两个接口要求的方法。 public void swim() {System.out.println("swim01");} public void fly() {System.out.println("fly01");} } public class Adventure { //这里定义4个函数,实际是用来体现子类向上转型时,可以作为不同基类的参数输入。 public static void t(CanFight x) {x.fight();} public static void u(CanSwim x) {x.swim();} public static void v(CanFly x) {x.fly();} public static void w(ActionCharacter x) {x.fight();} public static void main(String[] args) { // TODO Auto-generated method stub //子类对象 Hero hero = new Hero(); //同一个参数,调用时,方法参数类型不同,实现向上转型 t(hero); //这里看做是一个CanFight u(hero); v(hero); w(hero);//这里看做是一个ActionCharacter } }
输出结果为:
fight01 swim01 fly01 fight01Adventure类中,四个方法把不同接口和具体类作为参数。当Hero对象创建后,可以传给这些方法,它会被向上转型称为每一个接口。采用这种机制,防止客户端程序员创建该类的对象,并确保这仅仅是建立一个接口。
好处仅仅如此?那为什么需要多重继承?--看了一些实践的代码,有感觉了。就是,你实现一个类,它可以遵循多个定义好的接口标准。这就是好处。
4、建议,如果知道某事物应该成为一个基类,第一选择应该是使它成为一个接口。
5、这里有强调:使用接口的核心原因:为了能够向上转型为多个基类型。(实际这里不是要求转型,因为上级也没定义实现,而是说实现的代码同时遵循多种接口标准,具有多重能力,且对外表现是可预期的(因为有基类方法约束))。
通过继承来扩展接口
1、如继承类一样,接口也可以继承,并可以添加新的方法声明。如:package C_09; //继承关系 //A---B------|----D // C------+ interface A{ void f1(); } interface B extends A{ void f2(); } interface C{ void f3(); } interface D extends B,C{ void f4(); }
A是接口,B继承自A,C是独立接口,D继承自B,C。
在定义实现接口的类时,后面继承的可以重载前面的。
如:实现接口B
//针对B接口,需要实现f1,f2两个方法 class ClassB implements B{ public void f1() {System.out.println("ClassB--f1()");} public void f2() {System.out.println("ClassB--f2()");}
实现接口D的时候,就得把前面的都实现了。
//定义实现接口的类 class ClassD implements D{ public void f1(){System.out.println("ClassD--f1()");} public void f2(){System.out.println("ClassD--f2()");} public void f3(){System.out.println("ClassD--f3()");} public void f4(){System.out.println("ClassD--f4()");} }注意,虽然ClassB实现了B的接口,但与ClassD没有什么关系,在D里面都得实现。
然后再一个类里面创建相应对象,体现对这些接口的使用。
public class HorrorShow { //方法定义输入参数为基类接口 static void u(A a) {a.f1();} static void v(B b) { b.f1(); b.f2(); //注意,这里因为参数为基类接口,所以,即使实际传入的参数是子类对象,已经实现了子接口的方法。 } public static void main(String[] args) { // TODO Auto-generated method stub //用上一级的基类来声明变量,具体对象还得用实现类来创建。 D varClassD = new ClassD(); varClassD.f1(); varClassD.f2(); varClassD.f3(); varClassD.f4(); // System.out.println("-------------"); B varClassB = new ClassB(); varClassB.f1(); varClassB.f2(); System.out.println("-------------"); u(varClassB); v(varClassB); System.out.println("-------------"); u(varClassD); v(varClassD); // A varInterfaceA = new } }输出如下:
ClassD--f1()
ClassD--f2()
ClassD--f3()
ClassD--f4()
-------------
ClassB--f1()
ClassB--f2()
-------------
ClassB--f1()
ClassB--f1()
ClassB--f2()
-------------
ClassD--f1()
ClassD--f1()
ClassD--f2()
注意:尽量避免在不同接口中使用相同的方法名,通常会造成混乱。
适配接口
1、从接口的使用上来看,很明显,同一个接口可以具有多个不同的实现。2、其效果就是,不管你怎么实现你的类方法,只要你遵循一个接口,其他人就知道怎么调用了。
3、可以在任何现有类上添加新的接口。
4、这里特别介绍一下Sanner类。
1)java.util.Scanner是Java5的新特征,主要功能是简化文本扫描。
2)Scanner的构造器支持多种方式,可以从字符串(Readable)、输入流、文件等等来直接构建Scanner对象,有了Scanner了,就可以逐段(根据正则分隔式)来扫描整个文本,并对扫描后的结果做想要的处理。
3)它可以接受一个Readable接口(专为Scanner设计的)的构造器。
4)如果想让Scanner作用于一个类,就可以通过让它实现Readabl接口。只要实现其read()方法,就可以用Scanner作用到新定义的类了。实现read(CharBuff cb),把要被扫描的数据添加到cb中去,就可以用Scanner访问了。具体参见书上代码吧。
接口中的域--用接口实现枚举
1、放入接口中的任何域都自动是static和final的。所以接口也可以用来创建常量。在Java SE5之前,这是产生于C的枚举类型具有相同效果的唯一途径。2、可以用常量直接赋值,也可以用表达式初始化。
package C_09; import java.util.Random; public interface EnumTest { int ONE =1, TWO =2; //直接赋值 Random RAND = new Random(40); int RANDOM_INT = RAND.nextInt(10); //用表达式初始化 long RANDOM_LONG = RAND.nextLong()*10; double RANDOM_DOUBLE=RAND.nextDouble()*10; }
3、然后就可以直接用了,如下:
package C_09; import C_09.EnumTest; public class TestEnumInterface { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println(EnumTest.ONE); System.out.println(EnumTest.RANDOM_DOUBLE); System.out.println(EnumTest.RANDOM_INT); System.out.println(EnumTest.RANDOM_LONG); } }输出如下:
1 6.501284755664213 2 -1341133541859225106
------------2018.1.20 23:32 深圳
相关文章推荐
- Java编程思想 第9章 接口
- JAVA编程思想(5) - 接口(一)
- java编程思想(初始化与清理,访问权限控制,复用类,多态,接口,内部类)
- 56.java编程思想——创建窗口和程序片 用户接口API
- Java编程思想之9接口
- java编程思想——接口和抽象类的区别
- Java编程思想——接口
- java编程思想阅读笔记(四)接口与内部类
- java编程思想3感悟(7)---抽象基类和接口、并发
- Java编程思想-09接口
- Java编程思想接口
- Java编程思想-接口与内隐类(1)
- java编程思想9.5——异常的限制(继承与实现接口情况下,读书笔记)
- java编程思想笔记09-接口
- Java编程思想(六) —— 接口
- JAVA编程思想-第九章 接口
- java编程思想-接口
- java编程思想之接口
- 《Java编程思想 Generics》读书笔记一——泛型的基础知识
- java编程思想 第十三章 正则表达式