42
6: Reusing Classes 复复复复复 java 复复复复复复复复复复一) One of the most compelling( 引引引引 ) featur es about Java is code reuse. But to be revo lutionary, you’ve got to be able to do a lo t more than copy code and change it 引引引引引引引引引引引 引引. That’s the approach used in procedur That’s the approach used in procedur al languages like C, and it hasn’t worked al languages like C, and it hasn’t worked very well. Like everything in Java, the so very well. Like everything in Java, the so lution revolves around the class. You reus lution revolves around the class. You reus e code by creating new classes, but instea e code by creating new classes, but instea d of creating them from scratch, d of creating them from scratch, you use e you use e xisting classes that someone has already b xisting classes that someone has already b uilt and debugged. uilt and debugged. The trick 复复复 () is to use the class es without soiling 复复复 () the existing code.

6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

  • Upload
    selah

  • View
    144

  • Download
    0

Embed Size (px)

DESCRIPTION

6: Reusing Classes (复用代码是 java 众多引人注目的功能之一). - PowerPoint PPT Presentation

Citation preview

Page 1: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

6: Reusing Classes (复用代码是 java 众多引人注目的功能之一) One of the most compelling( 引人注目 ) features about Java is code reuse. But to be revolutionary, you’ve got to be able to do a lot more than copy code and change it (仅仅拷贝和加以修改是不够的) .

That’s the approach used in procedural languaThat’s the approach used in procedural languages like C, and it hasn’t worked very well. Like eveges like C, and it hasn’t worked very well. Like everything in Java, the solution revolves around the clarything in Java, the solution revolves around the class. You reuse code by creating new classes, but instess. You reuse code by creating new classes, but instead of creating them from scratch, ad of creating them from scratch, you use existing clyou use existing classes that someone has already built and debugged.asses that someone has already built and debugged. The trick (窍门) is to use the classes without soiling (污染) the existing code.

Page 2: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

In this chapter you’ll see two ways to accomplisIn this chapter you’ll see two ways to accomplish this.h this. The first is quite straightforward: you simply create objects of your existing class inside the new class. This is called composition, because the new class is composed of objects of existing classes. You’re simply reusing the functionality of the code, not its form.

The second approach is more subtlesubtle. It creates a new class as a type of an existing class. You literally take the form of the existing class and add code to it without modifying the existing class. This magical act( 神奇的行为 ) is called inheritance, and the compiler does most of the work. Inheritance is one of the cornerstones (基石) of object-oriented programming.

Page 3: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

6.1 Composition 6.1 Composition syntaxsyntax

WaterSource

WaterSource()

SprinklerSystemprivate WaterSource source;

public static void main( .. )

sprinklers

new

将 WaterSource 置于新类中

Page 4: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

6.1 Composition 6.1 Composition syntaxsyntax

Until now, composition has been used quite frequently. You simply place object references inside new classes.//: c06:SprinklerSystem.java

// Composition for code reuse.class WaterSource { private String s; WaterSource() { System.out.println("WaterSource()"); s = new String("Constructed"); } public String toString() { return s; } }

public class SprinklerSystem { private String valve1, valve2, valve3, valve4; private WaterSource source; private int i; private float f; public String toString() { return "valve1 = " + valve1 + "\n" + "valve2 = " + valve2 + "\n" + "valve3 = " + valve3 + "\n" + "valve4 = " + valve4 + "\n" + "i = " + i + "\n" + "f = " + f + "\n" + "source = " + source; }

Page 5: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

public static void main(String[] args) { SprinklerSystem sprinklers = new SprinklerSystem(); System.out.println(sprinklers); } } ///:~

Primitives that are fields in a class are automatically initialized to zero; But the object references are initialized to null;( 对象引用会被初始化为 null) if you try to call methods for any of them, you’ll get an exception.

Page 6: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

It makes sense( 这是有意义的 ) that the compiler doesn’t just create a default object for every reference, because that would incur (招致) unnecessary overhead (负担) in many cases. If you want the references initialized, you can do it:1. At the point the objects are defined (在定义对象的地

方) . This means that they’ll always be initialized before the constructor is called.2. In the constructor for that class (在构造器中) .3. Right before you actually need to use the object (在使用之前) . This is often called lazy initialization. It can reduce overhead in situations where object creation is expensive and the object doesn’t need to be created every time.

Page 7: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

//: c06:Bath.java// Constructor initialization with composition.class Soap { private String s; Soap() { System.out.println("Soap()"); s = new String("Constructed"); } public String toString() { return s; }}

All three approaches are shown here:

2 、在构造器中

One reference

Page 8: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

public class Bath { private String // Initializing at point of definition: s1 = new String("Happy"), s2 = "Happy", s3, s4; private Soap castille; private int i; private float toy; public Bath() { System.out.println("Inside Bath()"); s3 = new String("Joy"); i = 47; toy = 3.14f; castille = new Soap(); }

1 、在对象定义的地方

2 、在构造器中

Page 9: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

public String toString() { if(s4 == null) // Delayed initialization: s4 = new String("Joy"); 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(); System.out.println(b); } } ///:~

3 、在要用之前。

Page 10: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

6.2 Inheritance syntax6.2 Inheritance syntax (继承语法)

Inheritance is an integral(Inheritance is an integral( 不可缺少的不可缺少的 ) part of Java (and al) part of Java (and all OOP languages).l OOP languages). It turns out It turns out (总是在产生)(总是在产生) that you’re that you’re always doing inheritance when you create a class, becausalways doing inheritance when you create a class, because unless you explicitly inherit from some other class, you e unless you explicitly inherit from some other class, you implicitly inherit from Java’s standard root class implicitly inherit from Java’s standard root class ObjectObject..

The syntax for composition is obvious, but to perform inheritance there’s a distinctly different form. When you inherit, you say “This new class is like that old class.”

Page 11: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

//: c06:Detergent.java // Inheritance syntax & properties. (清洁剂) class Cleanser { private String s = new String("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(); x.dilute(); // 稀释 x.apply(); x.scrub(); System.out.println(x); } }

Page 12: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

public class Detergent extends Cleanser {// Change a method: public void scrub() { ( 这个方法的输出变的有两部分 ) append(" Detergent.scrub()"); super.scrub(); // Call base-class version } // Add methods to the interface: public void foam() { append(" foam()"); } // Test the new class: public static void main(String[] args) { Detergent x = new Detergent(); x.dilute(); x.apply(); x.scrub(); x.foam(); System.out.println(x); System.out.println("Testing base class:"); Cleanser.main(args); } } ///:~

(去垢剂)

Page 13: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

基类的输出

派生类的输出

Page 14: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

This demonstrates a number of features. ( 这个程序示范了 JAVA 的许多特性 ) First, in the Cleanser append( ) method, Strings are concatenated to s using the += operator, which is one of the operators (along with ‘+’) that the Java designers “overloaded” to work with Strings. (将字符串重载) Second, both Cleanser and Detergent contain a main( ) method. You can create a main( ) for each one of your classes, and it’s often recommended to code this way so that your test code is wrapped (预先包装的) in with the class. (有 main( ) 便于测试程序)

Page 15: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

It’s important that all of It’s important that all of the the methods methods in Cleanser are in Cleanser are public. public.

Note that Note that CleanserCleanser has a set of methods has a set of methods in its interface: in its interface: append( )append( ), , dilute( )dilute( ), , appapply( )ly( ), , scrub( )scrub( ), and , and toString( )toString( ). Because . Because DetergentDetergent is is derived fromderived from CleanserCleanser (via (via the the extendsextends keyword), it automatically g keyword), it automatically gets all these methods in its interface, eveets all these methods in its interface, even though you don’t see them all explicin though you don’t see them all explicitly defined in tly defined in DetergentDetergent. You can think . You can think of inheritance, then, as reusing the classof inheritance, then, as reusing the class..

Page 16: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

In Detergent.main( ) you can see In Detergent.main( ) you can see that for a Detergent object, you can that for a Detergent object, you can call all the methods that are call all the methods that are available in Cleanser as well as in available in Cleanser as well as in Detergent (i.e., foam( )). Detergent (i.e., foam( )).

如果没有访问权限修饰符,成员的缺省访问权限是如果没有访问权限修饰符,成员的缺省访问权限是“包访问”。“包访问”。

Page 17: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

1 、阅读下面的程序并写出类 MyClass3 的所有成员,并写明它们定义自哪里。class MyClass1{ private int pro11; double pro12;}class MyClass2 extends MyClass1{ private double pro12; int pro21;}class MyClass3 extend MyClass2{ private int pro21; double pro31;}

修改这个程序,表明类MyClass3的所有成员要用到main()函数

只能在超类重用

没有修饰就是包限制

Page 18: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

public class MyClass{public static void main(String args[]){ MyClass3 x=new MyClass3();

x.pro11=55;x.pro12 =3.14;x.pro21 =77; x.pro31 = 3.1415926; System.out.println(x.pro21); System.out.println(x.pro31);

}}

Pro21 被去掉了private

Page 19: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

2 、定义—个类 MyRectangle 代表矩形,为矩形定义 g

etLength 方法(获得矩形的长度)、 getWidth 方法(获得矩形的宽度)、 setLength 方法(设置矩形的长度)、setWidth 方法(设置矩形的宽度)、 getArea 方法(求矩形的面积)和 toString 方法(显示矩形的格式) ;

为矩形派生出一个子类 MySquare 代表正方形,并对 getArea 和 toString 进行重写。并编写程序进行测试。

Page 20: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

public class MySquare extends MyRectangle{public MySquare(){ } public MySquare(int Length,int Width){ l=Length; w=Width; } public static void main(String args[]){ MySquare x=new MySquare(6,6); System.out.println(getArea()); System.out.println(x.toString());}}

public class MyRectangle{ static int l; static int w; public MyRectangle(){ } public MyRectangle(int Length,int Width){ l=Length; w=Width; } public double getLength(){ return l; } public double getWidth(){ return w; } public static double getArea(){ return l*w; } public String toString(){ return "the area is"+getArea()+"nn"; } public double setLength(int Length){ l=Length; return l; } public double setWidth(int Width){ w=Width; return w; }public static void main(String args[]){ MyRectangle x=new MyRectangle(3,6); System.out.println(getArea()); System.out.println(x.toString());}}

Page 21: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

Initializing the base class ( 初始化基类 )

It’s essential that the base-class subobject be initialized correctly, and there’s only one way to guarantee this: perform the initialization in the constructor by calling the base-class constructor, which has all the appropriate knowledge and privileges to perform the base-class initialization. Java automatically inserts calls to the base-class constructor in the derived-class constructor. The following example shows this working with three levels of inheritance:

Page 22: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

//: c06:Cartoon.java // Constructor calls during inheritance. import com.bruceeckel.simpletest.*; class Art { Art()Art() { System.out.println("Art constructor"); } } class Drawing extends Art { Drawing()Drawing() { System.out.println("Drawing constructor"); } } public class Cartoon extends Drawing { private static Test monitor = new Test(); public Cartoon()Cartoon() { System.out.println("Cartoon constructor"); } public static void main(String[] args) { Cartoon xx = new Cartoon(); monitor.expect(new String[] { "Art constructor", "Drawing constructor", "Cartoon constructor" }); } } ///:~

Art constructor Drawing constructor Cartoon constructor

类构造器

Page 23: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

Constructors with argumentsConstructors with arguments(带参数的构造器)

The preceding example has default constructorThe preceding example has default constructors; that is, they don’t have any arguments. It’s s; that is, they don’t have any arguments. It’s easy for the compiler to call these because easy for the compiler to call these because therthere’s no question about what arguments to pass.e’s no question about what arguments to pass. If your class doesn’t have default arguments, If your class doesn’t have default arguments, or or if you want to call a base-class constructor thif you want to call a base-class constructor that has an argument, you must explicitly write that has an argument, you must explicitly write the calls to the base-class constructor using the e calls to the base-class constructor using the susuperper keyword and the appropriate argument list: keyword and the appropriate argument list:

Page 24: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

//: c06:Chess.java // Inheritance, constructors and arguments. import com.bruceeckel.simpletest.*; class Game { Game(int i) { System.out.println("Game constructor"); } } class BoardGame extends Game { BoardGame(int i) { super(i); System.out.println("BoardGame constructor"); } } public class Chess extends BoardGame { private static Test monitor = new Test(); Chess() { super(11); System.out.println("Chess constructor"); } public static void main(String[] args) { Chess xx = new Chess(); } } ///:~

monitor.expect(new String[] { "Game constructor", "BoardGame constructor", "Chess constructor" });

类构造器

If you don’t call the base-class constructor in BoardGame( ), the compiler will complain that it can’t find a constructor of the form Game( ). In addition, the call to the base-class constructor must be the first thing you do in the derived-class constructor. (The compiler will remind you if you get it wrong.)

Page 25: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

6.3 Combining composition and inheritance6.3 Combining composition and inheritance

It is very common to use composition and inheritance together. The following example shows the creation of a more complex class, using both inheritance and composition, along with the necessary constructor initialization:

DinnerPlatePlate

Knife

Utensil

Spoon

Fork

Custom

PlaceSetting要好好的研究这个程序!

Page 26: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

Java doesn’t have the C++ concept of a Java doesn’t have the C++ concept of a destructordestructor, , a method that is automatically called when an object a method that is automatically called when an object is destroyed. The reason is probably that in Java, is destroyed. The reason is probably that in Java, the the practice is simply to forget about objects rather than practice is simply to forget about objects rather than to destroy them,to destroy them, allowing the garbage collector to re allowing the garbage collector to reclaim the memory as necessary.claim the memory as necessary.

6.3.1 Guaranteeing proper cleanup

you can’t know when the garbage collector will be called, or if it will be called. So if you want something cleaned up for a class, you must explicitly write a special method to do it, and make sure that the client programmer knows that they must call this method.

Page 27: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

In main( ), you can see two keywords that are new, and won’t officially (正式地) be introduced until Chapter 9: try and finally. The try keyword indicates that the block that follows (delimited by curly braces) is a guarded region (保护区) , which means that it is given special treatment. One of these special treatments is that the code in the finally clause following this guarded region is always executed (总是被执行) , no matter how the try block exits. (With exception handling, it’s possible to leave a try block in a number of nonordinary ways.) Here, the finally clause is saying “always call dispose( ) for x (一定要为 X 调用…) , no matter what happens.” These keywords will be explained thoroughly in Chapter 9.

Page 28: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

6.6 Incremental development6.6 Incremental development (增量开(增量开发)发) One of the advantages of inheritance is that it supports One of the advantages of inheritance is that it supports iincremental developmentncremental development. . You can introduce new code without causing bugs in exiYou can introduce new code without causing bugs in existing code; in fact, sting code; in fact, you isolate new bugs inside the new cyou isolate new bugs inside the new code.ode. By inheriting from an existing, functional class and By inheriting from an existing, functional class and adding fields and methods (and redefining existing methadding fields and methods (and redefining existing methods), you leave the existing code—that someone else migods), you leave the existing code—that someone else might still be using—untouched and unbugged. ht still be using—untouched and unbugged. If a bug happens, you know that it’s in your new code, If a bug happens, you know that it’s in your new code, which is much shorter and easier to read than if you had which is much shorter and easier to read than if you had modified the body of existing code.modified the body of existing code. It’s rather amazing how cleanly the classes are separateIt’s rather amazing how cleanly the classes are separatedd (类被隔离的如此干净,实在令人惊奇。)(类被隔离的如此干净,实在令人惊奇。) . .

Page 29: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

It’s important to realize that program develoIt’s important to realize that program development is an incremental process, pment is an incremental process, just like human leajust like human learning.rning. You can do as much analysis as you want, but you s You can do as much analysis as you want, but you still won’t know all the answers when you set out on till won’t know all the answers when you set out on a project. a project. You’ll have much more success—and more imme You’ll have much more success—and more immediate feedback—diate feedback—if you start out to “grow” your projif you start out to “grow” your project as an organic, evolutionaryect as an organic, evolutionary (进化的) (进化的) creaturecreature, r, rather than constructing it all at once like a glass-box ather than constructing it all at once like a glass-box skyscraper.skyscraper.

Page 30: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

6.7 Upcasting6.7 Upcasting(( 向上转型向上转型 )) The most important The most important

aspect of inheritance aspect of inheritance is not that it provides is not that it provides methods for the new methods for the new class. It’s the class. It’s the relationshiprelationship expressed between expressed between the new class and the the new class and the base class. This base class. This relationship can be relationship can be summarized by summarized by saying, saying, “The new “The new class class is a type ofis a type of the the existing class.”existing class.”

import java.util.*; class Instrument { public void play() {} static void tune(Instrument i) { // ... i.play(); } } // Wind objects are instruments // because they have the same interface: public class Wind extends Instrument { public static void main(String[] args) { Wind flute = new Wind(); Instrument.tune(flute); // Upcasting } } ///:~ The act of converting a Wind reference into an Instrument reference is called upcasting.

Page 31: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

Why “upcasting”?Why “upcasting”? The reason for the term is historical, and based on the way The reason for the term is historical, and based on the way

class inheritance diagrams have traditionally been drawn: class inheritance diagrams have traditionally been drawn: with the root at the top of the page, growing downward. with the root at the top of the page, growing downward. (Of course, you can draw your diagrams any way you find (Of course, you can draw your diagrams any way you find helpful.) The inheritance diagram for helpful.) The inheritance diagram for Wind.javaWind.java is then: is then:

Instrumnt

Wind

Casting from a derived type to a base type ( 由导出类转型为基类 )moves up on the inheritance diagram, so it’s commonly referred to as upcasting. Upcasting is always safe because you’re going from a more specific type to a more general type. That is, the derived class is a superset of the base class. It might contain more methods than the base class, but it must contain at least the methods in the base class.导出类是基类的一个超集。

Page 32: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

6.8 The final 6.8 The final keywordkeyword

Java’s Java’s finalfinal keyword has slightly different me keyword has slightly different meanings depending on the context, but in generaanings depending on the context, but in general it says l it says “This cannot be changed.”“This cannot be changed.” You mig You might want to prevent changes for two reasons: deht want to prevent changes for two reasons: design or efficiency. Because these two reasons asign or efficiency. Because these two reasons are quite different, it’s possible to misuse(re quite different, it’s possible to misuse( 误误用用 ) the ) the finalfinal keyword. keyword. The following sections discuss the three places The following sections discuss the three places where where finalfinal can be used: for can be used: for data, methods, andata, methods, and classes.d classes.

Page 33: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

6.8.1 Final data 6.8.2 Final methods

6.8.2 Final classes6.8.2 Final classesWhen you say that an entire class is final (by preceding its definition with the final keyword), you state that you don’t want to inherit from this class or allow anyone else to do so. In other words, for some reason the design of your class is such that there is never a need to make any changes (永远不需要) , or for safety or security reasons you don’t want subclassing.

Page 34: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

//: c06:Jurassic.java // Making an entire class final. class SmallBrain {} final class Dinosaur { int i = 7; int j = 1; SmallBrain x = new SmallBrain(); void f() {} }//! class Further extends Dinosaur {} // error: Cannot extend final class 'Dinosaur‘ public class Jurassic { public static void main(String[] args) { Dinosaur n = new Dinosaur(); n.f(); n.i = 40; n.j++; } } ///:~

Page 35: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)
Page 36: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

6.11 6.11 SummarySummary

Despite the strong emphasis on inheritance in object-Despite the strong emphasis on inheritance in object-oriented programming, when you start a design oriented programming, when you start a design you you should generally prefer compositionshould generally prefer composition during the first cut during the first cut and use inheritance only when it is clearly necessary. and use inheritance only when it is clearly necessary. Composition tends to be more flexible.Composition tends to be more flexible. In addition, by In addition, by using the added artifice of inheritance with your member using the added artifice of inheritance with your member type, you can change the exact type, and thus the type, you can change the exact type, and thus the behavior, of those member objects at run time. behavior, of those member objects at run time. Therefore, you can change the behavior of the composed Therefore, you can change the behavior of the composed object at run time. object at run time.

When designing a system, your goal is to find or create a When designing a system, your goal is to find or create a set of classes in which each class has a specific use and is set of classes in which each class has a specific use and is neither too bigneither too big (encompassing so much functionality that (encompassing so much functionality that it’s unwieldy to reuse) it’s unwieldy to reuse) nor annoyingly smallnor annoyingly small (you can’t (you can’t use it by itself or without adding functionality). use it by itself or without adding functionality).

Page 37: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

7 7 Polymorphism(Polymorphism( 多态多态 ) ) Polymorphism is the third Polymorphism is the third

essential feature of an object-essential feature of an object-oriented programming language, oriented programming language, after data abstraction and after data abstraction and inheritance. inheritance.

1 2 3 4

你唱 --我唱 --大家唱 --

Page 38: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)
Page 39: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)

// 动物排队import java.util.*;class Animal{ void showMsg(){} void move(){}}class Dog extends Animal{ void showMsg(){System.out.print(" 这是一只小狗 !\t");}void move(){System.out.println(" 请站到左边队伍去 .");}}class Cat extends Animal{ void showMsg(){System.out.print(" 这是一只小猫 !\t");}void move(){System.out.println(" 请站到中间队伍去 .");}}class Horse extends Animal{ void showMsg(){System.out.print(" 这是一只小马 !\t");}void move(){System.out.println(" 请站到右边队伍去 .");}}// 随机产生一个动物class RandomGenAnimals{ private Random rand=new Random(); public Animal next(){switch(rand.nextInt(3)){ default:case 0: return new Dog();case 1: return new Cat();case 2: return new Horse();}}}public class Animals{ private static RandomGenAnimals gen=new RandomGenAnimals(); public static void main(String args[]){Animal dongwu[]=new Animal[10];for(int i=0;i<dongwu.length;i++) dongwu[i]=gen.next();for(int i=0;i<dongwu.length;i++){ dongwu[i].showMsg(); dongwu[i].move(); } }}

public class Animals{ private static RandomGenAnimals gen=new RandomGenAnimals();

public static void main(String args[]){Animal dongwu[]=new Animal[10];

for(int i=0;i<dongwu.length;i++) dongwu[i]=gen.next();

for(int i=0;i<dongwu.length;i++){ dongwu[i].showMsg();

dongwu[i].move();

Page 40: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)
Page 41: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)
Page 42: 6: Reusing Classes (复用代码是 java 众多引人注目的功能之一)