For example, in Java, if you define Cow and Pig types as subclasses of Animal (see inheritance) like this:
class Cow extends Mammal { public Tail m_tail; private Horns m_horns;
public void eat(Food f) { if (f.is_meat()) { return; // Cow won't eat } super.eat(f); chewcud(); } private void chewcud() { . . . } } class Pig extends Mammal { // No need to override Animal's eat() // function here; pigs will eat anything. }
Then you can declare a single variable that takes objects of either type, and call methods on that variable, like this:
Animal theAnimal = new Pig(); theAnimal.eat(table_scraps); theAnimal = new Cow(); theAnimal.eat(table_scraps);
In the above code, when the eat()method is called on theAnimal the first time (when it references the pig), the Pig class's eat() method will be called, which will accept the table scraps. When theAnimal is reset to point to the cow, Cow's eat() method is called instead, and it will reject the table scraps.
Polymorphism describes methods of different objects that have the same name (and usually the same parameter list), so that calling a.add(1) invokes a different function than b.add(1). In strongly typed languages[?], polymorphism implies in this example that objects "a" and "b" must be derived from the same parent type, so that they share a common interface (that of the parent) with the method "add", a method which however is implemented differently in "a" and "b".
The advantage of polymorphism is that clients (users) of objects can invoke methods on the objects without knowing their exact (concrete) type. In other words, each type of object "knows" how to correctly perform the operation "add"; the user of the object does not know the exact type of the object whose methods are being invoked, but does know that the object must support the behavior "add" in a conformant way (where "conformant" means conforming to the specification of "add", which is formally done with a precondition, postcondition, and invariant; see also Type theory).
Why is polymorphism important? Because it allows client programs to be written based only on the abstract interfaces of the objects which will be manipulated (this is also called interface inheritance[?]). This means that future extension in the form of new types of objects is easy, if the new objects conform to the original interface. In particular, with object-oriented polymorphism, the original client program does not even need to be recompiled (only relinked) in order to make use of new types exhibiting new (but interface-conformant) behavior! (In C++, for instance, this is possible because the interface definition for a class defines a memory layout, the virtual function table[?] describing where pointers to functions can be found. Future, new classes can work with old, precompiled code because the new classes must conform to the abstract class interface, meaning that the layout of the new class's virtual function table is the same as before; the old, precompiled code can still look at the same memory offsets relative to the start of the object's memory in order to find a pointer to the new function. It is only that the new virtual function table points to a new implementation of the functions in the table, thus allowing new, interface-compliant behavior with old, precompiled code.)
Since program evolution very often appears in the form of adding new types of objects (i.e. new classes), this ability to cope with and localize change that polymorphism allows is the key new contribution of object technology to software design.
Lots more to be said here, including generics...
Search Encyclopedia
|
Featured Article
|