Polymorphism is the third essential feature of a object-oriented programming Language,after data abastraction and inherit Ance.
It provides another dimension of separation of interface from implementation, to decouple what is from. Polymorphism allows improved code organization and readability as well as the creation of extensible programs that can be "Grown" isn't only during the original creation of the project, but also when new features is desired.
Polymorphism deals with decoupling in terms of types.
Polymorphism also called dynamic binding or late binding or run-time binding
Upcasting revisited forgetting the object type
The compiler can ' t know that this instrument reference points to a wind in the case and not a Brass or stringed.
Method-call binding
Connecting a method call to a method body is called binding. When binding was performed before the program was run (by the compiler and linker, if there is one), it ' s called early bind Ing. C compilers has only early binding.
The solution is called late binding, which means, the binding occurs at run time, and based on the type of object. Late binding is also called dynamic binding or runtime binding.
That's, the compiler still doesn ' t know the object type, but the method-call mechanism finds out and calls the correct me Thod body. (You can imagine that som sort of type information must is installed in the objects.
All method Binding in Java uses late binding unless the method is static or final (private methods is implicitly final). This means so ordinarily you don ' t need to make any decisions about whether late binding would occur--it happens Automat Ically
Only use FINLA as a design decision, and not as an attempt to improve performance.
Producing the Right Behavior extensibility
Polymorphism is a important technique for the programmer to "separate the things, the change from the thins that stay the Same. "
Pitfall: "Overriding" Private methods
public class Privateoverride {
private void F () {print ("Private f ()");}
public static void Main (string[] args) {
Privateoverride po = new Derived ();
PO.F ();
}
}
Class Derived extends Privateoverride {
public void F () {print ("Public f ()");}
}
Output: Private f ()
Derived ' s F () in the is a brand new method; It's not even overloaded,since the base-class version of F () isn ' t visible in Derived.
Pitfall:fields and Static methods
Only ordinary method CALSS can be polymorphic
For example, if you acces a field directly, then access'll be is resolved at compile time.
When a Sub object was upcast to a Super reference, any field accesses was resolved by compiler, and was thus not polymorphi C. In this example, different storage are allocated for Super.field and Sub.field. Thus, Sub actually contains, Fieldss called Field:its own and the one, it gets from Super. Howerver, the Super version in isn't the default that's produced when refer to field in Sub; In order to get the Super field you must explicitly say Super.field.
Although this seems like it could is a confusing issue, in practive it virtually never comes up. For the one thing, you'll generally make all the fields private and so are won ' t access them directly, but only as side effects of Calling methods. In addition, you probably won/t give the same name to a Base-class field and a Derived-class field, because its confusing.
Constructors and polymorphism
Constructors is isn't polymorphic (they ' re actually static methods, but the static declaration is implicit).
Order of constructor calls inheritance and cleanup
If You do has cleanup issues, you must is diligent and create a Dispose () method for you new class. And with inheritance, you must override Dispose () in the derived class if you had any special cleanup that must happen as Part of garbage collection. When you override Dispose () under an inherited class, it's important to remember to the Base-class version of Dispose (), Since otherwise the Base-class cleanup would no happen.
If one of the member objects is shared with one or more other objects, the problem becomes more complex and you cannot sim Ply assume that's can call Dispose (). In this case, reference counting is necessary to keep track of the number of objects that is still accessing a shared Object.
private int refcount = 0;
public void AddRef () {refcount++;}
PROTECTD void Dispose () {
if (--refcount = = 0) {
The specific Dispose
}
When you attach a Gkfx object to your class, you must remember to call ADDREF (), but the Dispose () method would keep Trac K of the reference count and decide when to actually perform the cleanup. This technique requires extra diligence to use, but if you're sharing objects that require cleanup you don ' t has much CH Oice.
Behavior of polymorphic methods inside constructors
Class Glyph {
void Draw () {print ("Glyph.draw ()");}
Glyph () {
Print ("Glyph () before Draw ()");
Draw ();
Print ("Glyph () after draw ()");
}
}
Class Roundglyph extends Glyph {
private int radius = 1;
Roundglyph (int r) {
Radius = R;
Print ("roundglyph.roundglyph (), radius =" + radius);
}
void Draw () {
Print ("Roundglyph.draw (), radius =" + radius);
}
}
public class Polyconstructors {
public static void Main (string[] args) {
New Roundglyph (5);
}
}/* Output:
Glyph () before draw ()
Roundglyph.draw (), radius = 0
Glyph () after draw ()
Roundglyph.roundglyph (), radius = 5
A good guideline for constructors are, "do as little as possible to set the object into a good state, and if you can Possib Ly avoid it, don ' t call any other methods in this class. " The only safe methods to call inside a constructor is those that is final in the base class. (This also applies to private methods, which is automatically final.)
Convariant return types
Java SE5 adds convariant return types, which means, a overridden method in a derived class can return a type derived From the type returned by the Base-class method
Designing with Inheritance
If you choose inheritance First when you ' re using a existing class to make a new class, things can become needlessly comp Licated.
A better approach is to choose composition first, especially when it's not obvious which one you should use.
A general guideline are "use Inheritance to express difference in behavior, and fields (composition) to express variations In the state.
Substitution vs. extension
It would seem that the cleanest-to-create an inheritance hierarchy are to take the "pure" approach. That's, only methods that has been established in the base class was overridden in the derived class.
All your need to do are upcast from the derived class and never look back to see what exact type of object you ' re dealing WI Th. Everything is handled through polymorphism.
This too is a trap. Extending the interface is the perfect solution to a particular problem. This can is termed an "is-like-a" relationship.
Downcasting and runtime type information
At run time this cast was checked to ensure that it was in fact the type of you think it was. If it isn ' t, you get a classcastexception.
The act of checking types at run time is called runtime type Identification (RTTI).
Summary
Thinking in Java,fourth Edition (Java programming Idea, Fourth edition) study notes (eight) polymorphism