分类:
2008-09-12 11:31:30
第八章 接口与内部类
接口(interface)是一个完全抽象类,它根本就没有提供任何具体实现,是“纯粹的”抽象类。接口也可以包含字段,但是他们隐式为static和final。
可以在interface前面添加public(但仅限于该接口在与器同名的文件被定义),或者不添加它而使其只是具有包访问权限,这样它就只能在同一个包内可用。
可以选择在接口中显示地将方法声明为public的,但即使你不这么做,他们也是public。因此,当要实现一个接口时,在接口中被定义的方法必须被定义为public;否则,他们将只能得到缺省的包访问权限,这样在方法被继承的过程中,其可访问权限就被降低,这是Java编译器所不允许的。
Instrument中没有任何方法被声明为public,但是他们自动被定义是public
class Wind implements Instrument {
public void play() {
System.out.println("Wind.play()");
}
public String what() { return "Wind"; }
public void adjust() {}
}
Java中多重继承
在打算组合的不同接口中使用相同方法名通常会造成代码可读性的混乱,应避免这种情况
interface I1 { void f(); }
interface I2 { int f(int i); }
interface I3 { int f(); }
class C { public int f() { return 1; } }
class C2 implements I1, I2 {
public void f() {}
public int f(int i) { return 1; } // overloaded
}
class C3 extends C implements I2 {
public int f(int i) { return 1; } // overloaded
}
class C4 extends C implements I3 {
// Identical, no problem:
public int f() { return 1; }
}
// Methods differ only by return type:
//! class C5 extends C implements I1 {}
//! interface I4 extends I1, I3 {} ///:~
接口可以嵌套在类或其他接口中
内部类
可以将一个类的定义放在另一个类的定义内部,这就是内部类。内部类是一种非常有用的特性,因为它允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性。内部类与组合是完全不同的概念
import com.bruceeckel.simpletest.*;
public class Parcel2 {
static Test monitor = new Test();
class Contents {
private int i = 11;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() { return label; }
}
public Destination to(String s) {
return new Destination(s);
}
public Contents cont() {
return new Contents();
}
public void ship(String dest) {
Contents c = cont();
Destination d = to(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel2 p = new Parcel2();
p.ship("Tanzania");
Parcel2 q = new Parcel2();
// Defining references to inner classes:
Parcel2.Contents c = q.cont();
Parcel2.Destination d = q.to("Borneo");
monitor.expect(new String[] {
"Tanzania"
});
}
} ///:~
如果像从外部类的非静态方法之外的任意位置创建某个内部类的对象,那么必须像在main()方法那样,具体地知名这个对象的类型:OuterClassName.InnerClassName。
普通类(非内部类)不能声明为private或protected;他们指可以被赋予public或者包访问权
在方法和作用域内的内部类
public class Parcel4 {
public Destination dest(String s) {
class PDestination
implements Destination {
private String label;
private PDestination(String whereTo) {
label = whereTo;
}
public String readLabel() { return label; }
}
return new PDestination(s);
}
public static void main(String[] args) {
Parcel4 p = new Parcel4();
Destination d = p.dest("Tanzania");
}
} ///:~
PDestination类是dest()方法的一部分,而不是Parcel4的一部分。(还要注意,可以在同一个子目录下的任意类中对某个内部类使用类标识符PDestination,这并不会有命名冲突)所以在dest()之外不能访问PDestination。
链接到外部类
内部类能访问外围对象的所有成员,而不需要任何特殊的调教。此外,内部类还拥有其外围类的所有元素的访问权。
为什么需要内部类
内部类继承自某个类或实现某个接口,内部类的代码操作创建它的外围类的对象。所以可以认为内部类提供了某种进入其外围类的窗口。
没有内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个实现,对于内部类都没有影响。
如果没有内部类提供的、可以继承多个具体的或抽象的类的能力,一些涉及与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效的实现了“多重继承”。也就是说,内部类允许继承多个非接口类型(类或抽象类)。
闭包与回调
闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域。通过这个定义,可以看出内部类是面向对象的闭包,因为它不仅包含外围类对象的信息,还自动拥有一个指向此外围类对象的引用,在此作用域内,内部类有权操作所有的成员,包括private成员。
Java最引人争议的问题之一是人们认为Java应该包含某种类似指针的机制,以允许回调,对象能携带一些信息,这些信息允许它在稍后的某个时刻调用初始的对象。Java没有包括指针。通过内部类提供闭包的功能是完美的解决方案,它闭执政更灵活、安全。