《Java程序设计英文版课件:ch7 Reusing classes》由会员分享,可在线阅读,更多相关《Java程序设计英文版课件:ch7 Reusing classes(38页珍藏版)》请在金锄头文库上搜索。
1、Chapter 7Reusing classes7 Reusing ClassesCompositionInheritanceChoosing composition vs. inheritanceUpcastingThe final keywordInitialization and class loadingExercisesOne of the most compelling features about Java is code reuse. The trick is to use the classes without soiling the existing code. In th
2、is chapter youll see two ways to accomplish this. The first is quite straightforward: You simply create objects of your existing class inside the new class. This is called composition The second approach is more subtle. It creates a new class as a type of an existing class. You literally take the fo
3、rm of the existing class and add code to it without modifying the existing class. This magical act is called inheritanceclass B extends A class B extends A B is a kind of A B is a kind of ADog extends Animal =Dog is a kind of Dog extends Animal =Dog is a kind of animal animal ExtendClassBaseBaseExte
4、ndClassBase ClassExtendDefinition Scope UMLComposition syntaxUntil now, composition has been used quite frequently. You simply place object references inside new classes. class Car Engine eng;Wheel w1,w2,w3,w4;-class WaterSource private String s; WaterSource() System.out.println(WaterSource(); s = n
5、ew String(Constructed); public String toString() return s; public class SprinklerSystem private String valve1, valve2, valve3, valve4; WaterSource source; int i; float f; public String toString() return valve1 = + valve1 + n + valve2 = + valve2 + n + valve3 = + valve3 + n + valve4 = + valve4 + n + i
6、 = + i + n + f = + f + n + source = + source; public static void main(String args) SprinklerSystem sprinklers = new SprinklerSystem(); System.out.println(sprinklers); /position2. toString3.nullvalve1 = null valve2 = null valve3 = null valve4 = null i = 0 f = 0.0 source = null Initialization Timing A
7、t the point the objects are defined. This means that theyll always be initialized before the constructor is called. In the constructor for that class. Right before you actually need to use the object. This is often called lazy initialization. It can reduce overhead in situations where object creatio
8、n is expensive and the object doesnt need to be created every time. public class SprinklerSystem private String valve1, valve2, valve3, valve4; WaterSource source; int i=10; float f=5.0; /specifying initpublic SprinklerSystem ()/constructor initvalve1=new String(“V1”);valve2=new String(“V2”);valve3=
9、new String(“V3”);valve4=new String(“V4”);public String toString() if(source=null) /lazy init source=new WaterSource();return “”; public static void main(String args) SprinklerSystem sprinklers = new SprinklerSystem(); System.out.println(sprinklers); Inheritance syntaxclass B extends A class B extend
10、s A B is a kind of A B is a kind of ADog extends Animal =Dog is a kind of animal Dog extends Animal =Dog is a kind of animal When you extend a class, you automatically get all the data members and methods in the base class. Youre always doing inheritance when you create a class, because unless you e
11、xplicitly inherit from some other class, you implicitly inherit from Javas standard root class Object class Creature String name; float age;Color color;void die() ;class Animal extends CreatureHead head; Foot feet;void move(float x,float y) int getHungryState();Do not overuse inheritanceAlthough inh
12、eritance gets a lot of emphasis while learning OOP, it doesnt mean that you should use it everywhere you possibly can. On the contrary, you should use it sparingly, only when its clear that inheritance is useful.class Cleanser private String s = new String(Cleanser); public void append(String a) s +
13、= a; public void dilute() append( dilute(); public void apply() append( apply(); public void scrub() append( scrub(); public void print() System.out.println(s); public static void main(String args) Cleanser x = new Cleanser(); x.dilute(); x.apply(); x.scrub(); x.print(); public class Detergent exten
14、ds Cleanser / Add methods to the interface: public void foam() append( foam(); / Change a method: OVERRIDE! (access specifier)public void scrub() append( Detergent.scrub(); super.scrub(); / Call base-class version / Test the new class: public static void main(String args) Detergent x = new Detergent
15、(); x.dilute(); x.apply(); x.scrub(); x.foam(); x.print(); System.out.println(Testing base class:); Cleanser.main(args); /: Overloading methods with base-classclass Homer char doh(char c) System.out.println(doh(char); return d; float doh(float f) System.out.println(doh(float); return 1.0f; class Mil
16、house class Bart extends Homer void doh(Milhouse m) public class Hide public static void main(String args) Bart b = new Bart(); b.doh(1); / doh(?) used b.doh(x); b.doh(1.0f); b.doh(new Milhouse(); /: Initializing the base classInheritance doesnt just copy the interface of the base class. When you cr
17、eate an object of the derived class, it contains within it a subobject of the base class. Java automatically inserts calls to the base-class constructor in the derived-class constructor. class Art Art() System.out.println(Art constructor); class Drawing extends Art Drawing() System.out.println(Drawi
18、ng constructor); public class Cartoon extends Drawing Cartoon() System.out.println(Cartoon constructor); public static void main(String args) Cartoon x = new Cartoon(); /: Art constructor Drawing constructor Cartoon constructor The above example has default constructors; that is, they dont have any
19、arguments. Its easy for the compiler to call these because theres no question about what arguments to pass. If your base-class doesnt have default constructor , or if you want to call a base-class constructor that has an argument, you must explicitly write the calls to the base-class constructor usi
20、ng the super keyword and the appropriate argument list:super(xxx)Super must be in the first line of constructor bodyConstructors with argumentsclass Game Game(int i) System.out.println(Game constructor); Game() System.out.println(Game default constructor); class BoardGame extends Game BoardGame(int
21、i) super(i); System.out.println(BoardGame constructor); public class Chess extends BoardGame Chess() super(11); System.out.println(Chess constructor); public static void main(String args) Chess x = new Chess(); /: /if its omitted, what will happen?/if its omitted, what will happen?DelegationIt is mi
22、dway between inheritance and composition.It is a special composition with concrete pattern. Guaranteeing proper cleanupJava doesnt have the C+ concept of a destructor, a method that is automatically called when an object is destroyed.So if you want something cleaned up for a class, you must explicit
23、ly write a special method to do it, and make sure that the client programmer knows that they must call this method. You should follow the same order that is imposed by a C+ compiler on its destructors: First perform all of the cleanup work specific to your class, in the reverse order of creation. im
24、port java.util.*; class Shape Shape(int i) System.out.println(Shape constructor); void cleanup() System.out.println(Shape cleanup); class Circle extends Shape Circle(int i) super(i); System.out.println(Drawing a Circle); void cleanup() System.out.println(Erasing a Circle); super.cleanup(); The best
25、tack to take is to leave the data members privateyou should always preserve your right to change the underlying implementation. In order to separate the interface from the implementation , you should set access specifiers as narrow as possible. Client programmers cant do anything but send messages t
26、o the public interface, then you can change anything thats not public (e.g., “friendly,” protected, or private) without requiring modifications to client code.When overriding a method, we cant narrow its access specifier (To ensure that all the interfaces of the base class are inherited. )Access spe
27、cifiers reviewavailable to anyone who inherits from this class or anyone else in the same package.import java.util.*; class Villain private int i; protected int read() return i; protected void set(int ii) i = ii; public Villain(int ii) i = ii; public int value(int m) return m*i; /package test;public
28、 class Orc extends Villain private int j; public Orc(int jj) super(jj); j = jj; public void change(int x) set(x); /: Protected membersChoosing composition vs. inheritanceComposition is generally used when you want the features of an existing class inside your new class, but not its interface. That i
29、s, you embed an object so that you can use it to implement functionality in your new class, but the user of your new class sees the interface youve defined for the new class rather than the interface from the embedded object.Choosing composition vs. inheritanceWhen you inherit, you take an existing
30、class and make a special version of it. In general, this means that youre taking a general-purpose class and specializing it for a particular need. The is-a relationship is expressed with inheritance, and the has-a relationship is expressed with compositionFor example, youll see that it would make n
31、o sense to compose a car using a vehicle objecta car doesnt contain a vehicle, it is a vehicle.protectedIn an ideal world, the private keyword would be enough. In real projects, there are times when you want to make something hidden from the world at large and yet allow access for members of derived
32、 classes.The protected keyword is a nod to pragmatism. It says “This is private as far as the class user is concerned, but available to anyone who inherits from this class or anyone else in the same package.” 20UpcastingThe most important aspect of inheritance is not that it provides methods for the
33、 new class. Its the relationship expressed between the new class and the base class. This relationship can be summarized by saying “The new class is a type of the existing class.” This description is not just a fanciful way of explaining inheritanceits supported directly by the language.UpcastingOne
34、 of the clearest ways to determine whether you should use composition or inheritance is to ask whether youll ever need to upcast from your new class to the base class. If you must upcast, then inheritance is necessary, but if you dont need to upcast, then you should look closely at whether you need
35、inheritance. / Inheritance & upcasting. 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 = n
36、ew Wind(); Instrument.tune(flute); / Upcasting /Instrument ii = flute;/ Instrument.tune(ii); /: The final keywordFinal datafinal makes the value a constant final makes the reference a constant. Once the reference is initialized to an object, it can never be changed to point to another object. Howeve
37、r, the object itself can be modified Blank finalsfields that are declared as final but are not given an initialization value. the blank final must be initialized (in constructor) before it is used The final keywordFinal argumentsThis means that inside the method you cannot change what the argument r
38、eference points to (primitive: or its value)Final methodsmethods behavior is retained during inheritance and cannot be overridden. Final classesState that you dont want to inherit from this class or allow anyone else to do so. class Value int i = 1; public class FinalData / Can be compile-time const
39、ants final int i1 = 9; static final int VAL_TWO = 99; / Typical public constant: public static final int VAL_THREE = 39; / Cannot be compile-time constants: final int i4 = (int)(Math.random()*20); static final int i5 = (int)(Math.random()*20); Value v1 = new Value(); final Value v2 = new Value(); st
40、atic final Value v3 = new Value(); / Arrays: final int a = 1, 2, 3, 4, 5, 6 ; public void print(String id) System.out.println( id + : + i4 = + i4 + , i5 = + i5); public static void main(String args) FinalData fd1 = new FinalData(); /! fd1.i1+; / Error: cant change value fd1.v2.i+; / Object isnt cons
41、tant! fd1.v1 = new Value(); / OK - not final for(int i = 0; i Static init-memory alloc & clear- Specifying init-constructorIn the process of loading a subclass, the loader notices that it has a base class, which will be loaded then. This will happen whether or not youre going to make an object of th
42、at base class. Next, the static initialization in the root base class is performed, and then the next derived class, and so on.Order1.Static init(Base)-Static init(Derived)2.memory alloc & clear3.Specifying init(Base)-constructor(Base)4.Specifying init(Derived)-constructor(Derived)1.class Insect 2.i
43、nt i = 9; 3.int j; 4.Insect() prt(i = + i + , j = + j); j = 39; 5.static int x1 = prt(static Insect.x1 initialized); 6.static int prt(String s) System.out.println(s); return 47; 7. 8.public class Beetle extends Insect 9.int k = prt(Beetle.k initialized); 10.Beetle() prt(k = + k); prt(j = + j); 11.st
44、atic int x2 = prt(static Beetle.x2 initialized); 12.public static void main(String args) 13.prt(Beetle constructor); 14.Beetle b = new Beetle(); 15. 16. /: 1.static Insect.x1 initialized2.static Beetle.x2 initialized3.Beetle constructor 4.i = 9, j = 0 5.Beetle.k initialized 6.k = 47 7.j = 39 (packag
45、e access)11234534467Exercises9. Create a base class with only a nondefault constructor, and a derived class with both a default (no-arg) and nondefault constructor. In the derived-class constructors, call the base-class constructor. =18. Create a class with a static final field and a final field and demonstrate the difference between the two.