http://www.cnblogs.com/wenruo/p/5366052.html
抽象类
当基类比较抽象的时候一些函数就无法实现。比如动物类,你可以知道猫如何叫狗如何叫,但你无法说清动物如何叫,于是对于比较抽象的基类,其中的一些方法可以只声明,不实现。这样的方法叫做抽象方法,含有抽象方法的类叫做抽象类。抽象方法和抽象类需要用关键字abstract来标识。
含有抽象方法的类的对象是不安全的,因此java中不允许创建抽象类的对象。
对于一个不含有抽象方法的类也可以设为抽象类,这样,就能限制这个类不能产生对象了。
接口
当一个类足够抽象,将不会实现任何方法。接口(interface)是一个完全抽象的类,不提供任何具体实现。
接口同类一样有public和默认(包)访问权限。
接口中的域默认是static和final的
接口中的方法默认是public的,所以继承的时候注意实现的时候要声明为public。
接口的用处和抽象类看起来并不相同。比如上面说的抽象基类动物类,动物会叫,继承类包括猫狗。但是汽车,电视都会“叫”,却并不合适继承,这时一个“声音”接口就比较合适。
接口的多重继承
Because an interface has no implementation at all—that is, there is no storage associated with an interface—there’s nothing to prevent many interfaces from being combined.
一个类可以实现多个接口,却只能继承一个类。接口可以继承多个接口。
1、一个类实现两个接口而两个接口的存在完全相同的方法时,实现一个就可以了。
interface A { void f(); } interface B { void f(); } class C implements A, B { @Override public void f() { System.out.println("f()"); } } public class Test { public static void main(String[] args) { new C().f(); } }
2、如果两个方法名字相同参数列表不同,会实现重载。
interface A { void f(int x); } interface B { void f(); } class C implements A, B { @Override public void f() { System.out.println("f()"); } @Override public void f(int x) { System.out.println("f(" + x + ")"); } } public class Test { public static void main(String[] args) { C c = new C(); c.f(); c.f(1); } }
3、如果参数列表相同,返回值不同,将会报错。
4、实现接口的方法也可以是继承自父类
interface A { void f(); } interface B { void f(); } class C { public void f() { System.out.println("f()"); } } class D extends C implements A, B { } public class Test { public static void main(String[] args) { D d = new D(); d.f(); } }
也就是对于一个实现接口的类,只要类中有接口所有函数的实现就可以。
但是注意,未通过implements实现接口,只有相同函数没有用的。
interface A { void f(); } class B { public void f(){}; } public class Test { public static void main(String[] args) { //A a = new B(); <-- Type mismatch: cannot convert from B to A } }
C++中存在菱形继承的问题。
class A{};
class B:public A{};
class C:public A{};
class D:public B,public C();
这样会出现一些问题,因为D中有两个A,因此调用A内的成员是编译器会分不清是哪个。【记得大概是这样吧。。C++无能。。。
java虽然不存在类的多重继承,但是存在接口多重继承。考虑下面的代码
interface F { void f(); } interface S1 extends F { void s1(); } interface S2 extends F { void s2(); } interface T extends S1, S2 { void t(); } class Fo implements T { public void f() { System.out.println("f"); } public void s1() { System.out.println("s1"); } public void s2() { System.out.println("s2"); } public void t() { System.out.println("t"); } } public class Diamond { public static void main(String[] args) { Fo fo = new Fo(); fo.f(); } }
其实由上面的讨论也可以想到这完全不会有问题。因为java的接口根本不提供具体实现。这也是Java设计单一继承和接口的原因。
接口中的域
定义时即要初始化,可以是被非常量的表达式初始化。
interface F { int i = 0;//int i; <- error int j = i; int k = j * 10; void f(); }
这些域不是接口的一部分,它们的值被存储在该接口的静态存储区域内。
配适器设计模式
某个现有的类的接口和需求不同,可以通过实现某个接口达到要求。(因为《thinking in java》提到所以稍微看了一下。。理解浅显。。
一般都是用插头举例,如果插头型号不合适就在外面在套一个转换插头实现工作。(原谅我是在写不出符合逻辑的例子。。。。。
class A { public void solveByA() {} } interface B { public void solveByB(); } class C { public static void solve(B b) { b.solveByB(); } } /* 想要在solve中调用A明显是不行的,于是加一个配适器给A,让它套一个B的外壳 */ class AImplementsB extends A implements B { @Override public void solveByB() { solveByA(); } } /* 由此可以想到对于所有的类 只要我们能对它实现接口B 就可以使该类作用于solve 提高了复用性 */ public class AdapterDemo { public static void main(String[] args) { C.solve(new AImplementsB()); } }
举个实际的用处。Scanner的构造器接受的是一个Readable接口,也就是说只要一个类实现了Readable接口,就可以使Scanner作用于它。
Readable接口中只有一个方法public int read(CharBuffer arg0);在read内部将输入内容添加到CharBuffer参数中,返回添加或者没有输入返回-1。
import java.nio.CharBuffer; import java.util.Random; import java.util.Scanner; public class RandomWords implements Readable { private static Random rand = new Random(); private static final char[] capitals = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm".toCharArray(); private int count = 0; public RandomWords(int count) { this.count = count; } @Override public int read(CharBuffer cb) { if (count-- == 0) return -1; cb.append(capitals[rand.nextInt(capitals.length)]); cb.append(" "); return 1; } public static void main(String[] args) { Scanner in = new Scanner(new RandomWords(10)); while (in.hasNext()) { System.out.print(in.next() + ","); } in.close(); } }
接口可以嵌套在其他类或接口中。
private 或 public 或 默认访问权限 都可以。
没弄明白什么用ing。