两种比较常见的方式:一种是“组合”即通过new对象;一种是“继承”。(一堆术语好气啊。。)而什么时候使用,继承=“is-a”(是一个),组合=“has-a”(有一个 ),一般我写程序组合和继承并用,比如汽车是一种车,这辆汽车上有座椅,那么汽车继承车,汽车又组合座椅。
客户端程序员编写的大部分代码就可以成为组合(听起来叫组合,通俗上理解就是你在类里new就可以称之为组合了)。继承(举个例子:给你一本已经写过一些内容的笔记,而你可以在笔记上添加新的内容也就是扩展,而你可以看到旧内容(继承)也可以写新内容),创建类就是在继承,都是在隐式继承object根类,而通过继承可以在其接口自动获取他自身的方法,虽然没办法看到他的显式定义,但是这也算一种对类的复用。
而还有一种介于组合和继承中间:代理(又是术语,通俗点理解:代理也就是代理商,而你代理的商品是不是通过厂家提供,那么商品很多,你可以自己决定你要卖什么跟厂家拿)。
public class SpaceShipControls {
void up(int velocity) {}
void down(int velocity) {}
void left(int velocity) {}
void right(int velocity) {}
void forward(int velocity) {}
void back(int velocity) {}
void turboBoost() {}
}
SpaceShipControls这个类里一堆方法,你如果直接extend,是不是所有方法都可以用,但是有时候会出现我想用一部分,而另一部分不想显示出来,这时候可以通过一个代理类。
public class SpaceShipDelegation {
private String name;
private SpaceShipControls controls =
new SpaceShipControls();
public SpaceShipDelegation(String name) {
this.name = name;
}
// Delegated methods:
public void back(int velocity) {
controls.back(velocity);
}
public void down(int velocity) {
controls.down(velocity);
}
public void forward(int velocity) {
controls.forward(velocity);
}
public void left(int velocity) {
controls.left(velocity);
}
public void right(int velocity) {
controls.right(velocity);
}
public void turboBoost() {
controls.turboBoost();
}
public static void main(String[] args) {
SpaceShipDelegation protector =
new SpaceShipDelegation("NSEA Protector");
protector.forward(100);
}
}
SpaceShipDelegation 在这个代理类中new出来SpaceShipControls,自己编写方法去调用他,然后除了up()方法,都在SpaceShipDelegation 基础上自己写方法去调用,这样,在SpaceShipDelegation 中可以拿到SpaceShipControls所有的方法,但是又可以只用到需要的方法。(不知道这样理解对不对。。)
既然复用,那就是也涉及到修饰符上,说到继承,一个类用protected修饰的成员(包括方法跟变量),继承这个类的类可以调用。
这里着重谈一下final修饰符:假设一个程序中需要重复用到你的名字,那么你的名字不会变吧,这时候可以定义一个常量final String =“名字”。final数据,final方法,final类。
这里说一下final方法吧,两种原因:一、可以防止被继承类方法不会被继承于他的类修改。二、效率。
在复用类中又涉及到一个程序加载顺序,了解可以对程序运行启动有一个全局判断。
class Insect {
private int i = 9;
protected int j;
Insect() {
print("i = " + i + ", j = " + j);
j = 39;
}
private static int x1 =
printInit("static Insect.x1 initialized");
static int printInit(String s) {
print(s);
return 47;
}
}
public class Beetle extends Insect {
private int k = printInit("Beetle.k initialized");
public Beetle() {
print("k = " + k);
print("j = " + j);
}
private static int x2 =
printInit("static Beetle.x2 initialized");
public static void main(String[] args) {
print("Beetle constructor");
Beetle b = new Beetle();
}
} /* Output:
static Insect.x1 initialized
static Beetle.x2 initialized
Beetle constructor
i = 9, j = 0
Beetle.k initialized
k = 47
j = 39
*///:~
在加载main时触发static变量加载,发现Beetle 继承Insect,所以又先到Insect中,如果Insect中又继承其他类,那再进入那个类进行变量初始化,以此类推一直到父类才开始进行变量加载,先static修饰的后非static修饰的然后又顶层的父类一直往下初始化,就好像下楼一样。
总结(偷懒):