复用类

组合语法

假设你需要创建一个具有多个基本数据类型,多个String对象,以及另一个类的对象。对于基本类型你可以直接定义,但对于非基本类型的对象,必须将其引用置于新的类中。

 

class WaterSoure{

       private String s;

       WaterSource(){

              System.out.println(“WaterSource()”);

              s=”Constructed”;

}

public String toString(){return s;}

}

public class SprinklerSystem{

       private String value1,value2,value3,value4;

       private WaterSource source=new WaterSource();

       private int i;

       private float f;

       public String toString(){

              return

                     “value1 =”+value1+” ”+

                     “value2 =”+value2+” ”+

                     “value3 =”+value3+” ”+

                     “value4 =”+value4+” ”+

                     “i =” +i+” “+”f=”+ f +” “+

              “source = “ + source;

}

public static void main(String[] args){

       SprinklerSystem sprinklers=new SprinklerSystem();

       System.out.println(sprinklers);

}

}

输出

WaterSource();

value1 = null value2 = null value3 = null value4 = null

i=0 f=0.0 source=Constructed

 

       在上面两个类中的方法中,有一个特殊的方法叫做toString().每一个非基本类型的对象都具有一个toString()方法。这个方法会在系统需要一个String对象的时候,而你却只有一个对象时被调用。所以在表达式中:

 “source =”+source;

系统知道你此时需要一个String对象,因为将一个String和另一个String相加,因此编译器将调用toString()方法,来吧source对象转化成一个String。因此每当你想创建的类需要具备此类功能的时候只需要编写toString()方法即可。

       上面的例子可以看出编译器自动为没有初始化的对象,赋予了默认值null.

       但编译器并不是简单的为每一个对象都创建默认对象,这样做的目的是为了个程序减少负担。如果想要初始化这些对象可以在代码以下位置进行。

       1,定义对象的地方,这意味着他们总是能够在构造器被调用之前被初始化。

       2,在类的构造器中。

       3,在使用对象之前(惰性初始化)。

       4,使用实例初始化。

      

class Soap{

       private String s;

       Soap(){

              System.out.println(“Soap()”);

              s= “Constructed”;

}

public String toString(){return s;}

}

 

public class Bath{

       private String //定义时初始化

       s1= “Happy”,

       s2=”Happy”,

       s3,s4;

       private Soap castile;

       private int i;

       private float toy;

       public Bath(){

              System.out.println(“Inside Bath()”);

              s3=”Joy”;

              toy=3.14f;

              castile=new Soap();

}

{i =47;}//实力初始化

public String toString(){

       if(s4==null)    //使用之前初始化

              s4=”Joy”

       return

                     “s1 =”+s1+”\n”+

                     “s2 =”+s2+”\n”+

                     “s3 =”+s3+”\n”+

                     “s4 =”+s4+”\n”+

                     “i =” +i+” “+”toy=”+ toy+” “+

                     “castille = “ + castille;

}

public static void main(String[] args){

       Bath b=new Bath();

       System.out.println(b);

}

}    

输出

Insid Bath();

Soap();

s1=Happy

s2=Happy

s3=Joy

s4=Joy

i=47

toy=3.14

castile=Constructed

继承语法

       继承是所有面向对象语言所不可或缺的部分。当创建一个类时,总是在继承(Object类)。

       不同于组合的语法,继承使用的是一种特殊的语法,在继承工程中,需要先生命“新类与旧类相似”、这种声明是通过在类主题左边的花括号之前,书写后面紧随基类名称关键字extends而实现的。当这么做时,会自动得到积累中所有的域和方法。例如:

class Cleanser{

       private String s=”Cleanser”;

       public void append(String a){s+=a;}

       public void dilute(){append(“ dilute()”);}

       public void apply(){append(“ apply()”);}

       public void scrub(){append(“ scrub()”);}

       public String toString(){return s;}

       public static void main(String[] args){

       Cleanser x=new Cleanser();

System.out.println(x);

}    

}

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 x=new Detergent();

              x.dilute();

              x.apply();

              x.scrub();

              x.foam();

              System.out.println(“Testing base class:”);

              Cleanser.main(args);

}

}

输出

Cleanser dilute() apply() Detergent.scrub() scrub() foam()

Cleanser dilute() apply() scrub()

 

这里使用了Java的许多新特性

1,  使用+=对字符串进行连接处理

2,  上面两个类均有main方法。可在每个类中都创建main方法,这样做可以让单元测试变得简单易行,此外即使一个程序中多个类也只有命令行调用的那个类的main()方法会被调用,此例中调用的java Detergent.而我们在Detergent.main()中调用了Cleanser.main().并将命令行获取的参数传给了它。当然,也可以传递任意的String数组。

3,  继承一个类,只能访问被继承类的public方法。如果不加访问修饰符,那么默认的访问权限是包访问权限,只可以包内成员访问。因此为了继承一般将所有的字段(数据成员)都设置成private,将所有的方法都设置成public.

4,  Cleanser中的一些方法,虽然在Detergent没有显示的定义,但是,由于Detergent是由关键字extendsCleanser导出的,因此Detergent自动获得了这些方法。所以可以将继承视作对类的复用。

5,  我们在子类中修改了scrub方法,可能你的修改需要调用父类中的方法,但是在scrub()中不能直接调用scrub(),因为这样做会产生递归,为解决此问题,Java用关键字super表示超类的意思(父类),当前类就是从超类继承来的,为此,表达式super.scrub()将调用父类中scrub()方法

6,  在继承的过程中,也可以在导出类中添加新方法,其添加方法与类中添加任意方法一样。

初始化基类

       由于涉及了继承,因此对于导出类从外部开来,他就像是一个与基类具有相同接口的新类,或许还会有一些额外的方法和域。单继承并不只是复制基类的接口,当创建了一个导出类的对象时,该对象包含了一个基类的子对象。这个子对象与你用基类直接创建的对象是一样的。二者区别在于,后者来自于外部,而类的子对象被包装在导出类对象内部。

       因此对积累子对象的正确初始化也是至关重要的。Java会在导出类的构造器中插入对基类构造器的调用。

       class Art{

              Art();

}

class Drawing extends Art{

       Drawing(){System.out.println(“Drawing constructor”);}

}

public class Cartoon extends Drawing{

       public Cartoon(){System.out.prinln(“Cartoon constructor”);}

       public static void main(String[] args){

       Cartoon x=new Cartoon();

}

}

输出

Art constructor

Drawing constructor

Cartoon constructor

 

从上例可以发现构造过程是从基类“向外”扩散的,所以基类在导出类构造器可以访问它之前,就已经完成了初始化。

posted on 2011-02-25 22:58  柠檬哥  阅读(236)  评论(0编辑  收藏  举报

导航