`
leonzhx
  • 浏览: 763107 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Chapter 8. Polymorphism -- Thinking in Java

阅读更多

1) Polymorphism is the third essential feature of an object-oriented programming language, after data abstraction and inheritance. It provides another dimension of separation of interface from implementation, to decouple what from how. Polymorphism allows improved code organization and readability as well as the creation of extensible programs that can be “grown” not only during the original creation of the project, but also when new features are desired. Polymorphism is also called dynamic binding or late binding or run-time binding.

 

2) Connecting a method call to a method body is called binding. When binding is performed before the program is run (by the compiler and linker, if there is one), it’s called early binding.

 

3) All method binding in Java uses late binding unless the method is static or final (private methods are implicitly final).

 

4) final method prevents anyone from overriding that method. Perhaps more important, it effectively “turns off” dynamic binding, or rather it tells the compiler that dynamic binding isn’t necessary. This allows the compiler to generate slightly more efficient code for final method calls. However, in most cases it won’t make any overall performance difference in your program, so it’s best to only use final as a design decision, and not as an attempt to improve performance.

 

5) If you access a field directly, that access will be resolved at compile time. If a method is static, it doesn’t behave polymorphically. (static methods are associated with the class, and not the individual objects.)

 

6) A constructor for the base class is always called during the construction process for a derived class, chaining up the inheritance hierarchy so that a constructor for every base class is called.

 

7) The order of constructor calls for a complex object is as follows:
    a. The base-class constructor is called. This step is repeated recursively such that the root of the hierarchy is constructed first, followed by the next-derived class, etc., until the most-derived class is reached.
    b. Member initializers are called in the order of declaration.

    c. The body of the derived-class constructor is called.

 

8) If you do have cleanup issues, you must be diligent and create a dispose( ) method (the name I have chosen to use here; you may come up with something better) for your new class. And with inheritance, you must override dispose( ) in the derived class if you have any special cleanup that must happen as part of garbage collection. When you override dispose( ) in an inherited class, it’s important to remember to call the base-class version of dispose( ) at last, since otherwise the base-class cleanup will not happen.

 

9) The order of disposal should be the reverse of the order of initialization, in case one subobject is dependent on another. For fields, this means the reverse of the order of declaration (since fields are initialized in declaration order). For base classes , you should perform the derived-class cleanup first, then the base-class cleanup. That’s because the derived-class cleanup could call some methods in the base class that require the base-class components to be alive, so you must not destroy them prematurely.

 

10) If you are sharing objects that require cleanup, reference counting may be necessary to keep track of the number of objects that are still accessing a shared object.

 

11) If you call a dynamically-bound method inside a constructor, the overridden definition for that method is used. If the constructor is only one step in building an object of a class that’s been derived from that constructor’s class, the derived parts have not yet been initialized at the time that the current constructor is being called. A dynamically bound method call, however, reaches “outward” into the inheritance hierarchy. It calls a method in a derived class. If you do this inside a constructor, you call a method that might manipulate members that haven’t been initialized yet.

 

public class TestB {
	public TestB () {
		b();
	}
	protected void b() {
	}
	public static void main(String[] a) {
		new TestC();
	}
}
class TestC extends TestB {
	int c = 2;
	protected void b () {
		System.out.println(c);
	}
}

 

12) The actual process of initialization is:
    a. The storage allocated for the object is initialized to binary zero before anything else happens.

    b. The base-class constructors are called as described previously.

    c. Member initializers are called in the order of declaration.
    d. The body of the derived-class constructor is called.

 

13) Java SE5 adds covariant return types, which means that an overridden method in a derived class can return a type derived from the type returned by the base-class method. Before Java SE5 only the exact same type can be returned from overridden method.

 

14) In Java, every cast is checked! So even though it looks like you’re just performing an ordinary parenthesized cast, at run time this cast is checked to ensure that it is in fact the type you think it is. If it isn’t, you get a ClassCastException. This act of checking types at run time is called runtime type identification (RTTI).

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics