第7章 复用类
java通过创建新类复用代码,还可以使用别人开发好的类。
组合和聚合 。参考:http://blog.csdn.net/liushuijinger/article/details/6994265
方法1:在新的类中创建已有类的对象。谓之组合。
方法2:按照已有类创建新类。位置继承。
7.1 组合语法
例子:
class WaterSource{ //水源
private String s;
WaterSource(){
System.out.println("WaterSource()");
s="constructed";
}
public String toString(){return s;}
}
public class SprinklerSystem{ // 洒水系统
private String valve1,valve2,valve3,valve4;
private WaterSource source=new WaterSource();
private int i;
private float f;
public String toString(){
return
"valve1="+valve1+" "+
"valve2="+valve2+" "+
"valve3="+valve3+" "+
"valve4="+valve4+"\n"+
"i="+i+" "+"f="+f+" "+"source="+source;
}
public static void main(String[] args){
SprinklerSystem sprinkler=new SprinklerSystem();
System.out.println(sprinkler);
}
}
结果:
WaterSource()
valve1=null valve2=null valve3=null valve4=null
i=0 f=0.0 source=constructed
分析:
要点1:在类SprinklerSystem中,有一个方法toString().每一个非基本类型的对象都有一个toString()方法,而且当编译器需要一个String而程序中只有一个对象时,该方法会被调用。所以SprinklerSystem.toString()的程序段“ “source=”+source; ”中,编译器会将字符串source= 和类WaterSource的对象source相加。这里对象source会转变为String类型。
要点2:类中域为基本类型时,编译器会自动初始化为0;但是如果是一个对象引用,会初始化NULL,调用方法会产生异常。
可以在以下4个位置初始化引用。
1.在定义对象的地方。这意味着它们总能够在构造器被调用之前被初始化。
2.在类的构造器中。
3.在将要使用这些对象之前,谓之惰性初始化。
4.直接实例初始化。
class Soap{ //肥皂
private String s;
Soap(){
System.out.println("Soap()"); //2.
s="constructed";
}
public String toString(){
return s;
}
}
public class Bath{ //浴室
private String s1="happy",s2="happy2",s3,s4;
private Soap castille;
private int i;
private float toy;
public Bath(){
System.out.println("Bath()");
s3="joy";
toy=3.14f;
castille=new Soap(); //1.
}
{i=47;}
public String toString(){
if(s4==null)
s4="joy"; //3.
return
"s1="+s1+"\n"+
"s2="+s2+"\n"+
"s3="+s3+"\n"+
"s4="+s4+"\n"+
"i="+i+"\n"+
"toy="+toy+"\n"+
"castille="+castille;
}
public static void main(String[] args){
Bath b=new Bath(); //4.
System.out.println(b);
}
}
结果:
Bath()
Soap()
s1=happy
s2=happy2
s3=joy
s4=joy
i=47
toy=3.14
castille=constructed
分析:
在类Bath的方法toString()被调用之前,s4会被初始化。
7.2 继承语法
所有的类都是从根类Object继承,使用关键字extends.
例子:
class Cleanser{ //清洁器
private String s="Cleanser";
public void append(String a){
s+=a;
}
public void dilute(){
append("dilute()");
}
public void apply(){
append("append()");
}
public void scrub(){
append("scrub()");
}
public String toString(){
return s;
}
public static void main(String[] args){
Cleanser c=new Cleanser();
c.dilute();
c.apply();
c.scrub();
System.out.println(c);
}
}
public class Detergent extends Cleanser{ //洗衣粉
public void scrub(){
append("Detergent.scrub()");
super.scrub();
}
public void foam(){
append("foam()");
}
public static void main(String[] args){
Detergent d=new Detergent();
d.dilute();
d.apply();
d.scrub();
d.foam();
System.out.println(d);
Cleanser.main(args); //输出基类的main函数
}
}
结果:
Cleanserdilute()append()Detergent.scrub()scrub()foam()
Cleanserdilute()append()scrub()
分析:
要点1: 在类Cleanser中,方法append()用“+=”链接字符串。或者“+”
要点2:类Cleanser和类Detergent都含有main()方法。便于单元测试。
要点3:类Cleanser中的方法都是public。
要点4:类Detergent中方法scrub(),super.scrub()会调用基类方法。
例子:子类初始化与基类的先后关系
class Art{
Art(){
System.out.println("Art constructor");
}
}
class Drawing extends Art{
Drawing(){
System.out.println("Drawing constructor");
}
}
public class Cartoon extends Drawing{
public Cartoon(){
System.out.println("Cartoon constructor");
}
public static void main(String[] args){
Cartoon c=new Cartoon();
}
}
结果:
Art constructor
Drawing constructor
Cartoon constructor
分析:
构建过程从基类到子类。
7.3 代理
结合 继承 和 组合 的折中方法,将一个对象至于新类中(类似组合),同时在新类中暴露 对象的所有方法(类似继承)。
例子:太空的控制模块的方法如下
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(){}
}
使用继承构造太空船。
public class SpaceShip extends SpaceShipControls{
private String name;
public SpaceShip(String name){
this.name=name;
}
public String toString(){
return name;
}
public static void main(String[] args){
SpaceShip spaceship=new SpaceShip("NSE");
spaceship.forward(100);
}
}
编译:若缺少“NSE”,出错。
SpaceShip.java:10: 错误: 无法将类 SpaceShip中的构造器 SpaceShip应用到给定类型;
SpaceShip spaceship=new SpaceShip();
^
需要: String
找到: 没有参数
原因: 实际参数列表和形式参数列表长度不同
1 个错误
使用代理:
public class SpaceShipDelegation{
private String name;
private SpaceShipControls controls=new SpaceShipControls();
public SpaceShipDelegation(String name){
this.name=name;
}
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 static void main(String[] args){
SpaceShipDelegation protector=new SpaceShipDelegation("NSEA");
protector.forward(100);
}
}
7.4 结合使用组合和继承