I'm writing a simple game where we have a collection of objects where a player moves around on a grid, collecting coin and avoid monsters.
My class structure looks as follows.
Game Controller - Responsible for spawning coins and tracking game state
Grid - A class which stores the objects which are currently on the grid, and a few grid related methods.
GridObject - An abstract class representing an object on the grid. e.g. player, monster or coin.
Player, Monster, Coin - All extend GridObject.
What is the most OOP way to program collision handling? The desired result is: Player hits Monster - end game, Player hits Coin - increase score, Monster hits Coin - nothing.
At present, when a GridObject moves, it notifies the board object that it wants to move; if this will cause a collision, I call a handler on the GameController (through a listener pattern), to handle the collision. In that handler, which takes two GridObjects as parameters, I'm using a lot of "instanceof" commands to distinguish the above cases.
What is the best way to avoid using all this "instanceof", which I have read usually means bad design?
What about introducing some interfaces :
interface Interactable {
InteractionResult interact(WorldEntity entity);
}
interface WorldEntity {
boolean isMonster();
boolean isPlayer();
boolean isPowerUp();
}
Now we can say that when a Player interacts with other things we can do :
public InteractionResult interact(WorldEntity entity) {
if(entity.isMonster()) {
return new DeathInteraction(this);
}
...
}
You don't eliminate all of the conditionals, but at least you start to organize your abstractions and decouple your classes.
Instead of using instanceof, you could use an enum in GridObject to determine the type. This way, you're just comparing an enum to check which objects are colliding. For example, (warning, syntax may not be exactly correct)
public enum ObjectType {
Player, Monster, Coin
}
private final ObjectType type;
public GridObject(ObjectType type) {
this.type = type;
}
public ObjectType getType() {return type;}
And then in your subclasses, you'll have to do the following:
public Player(your parameters) {
super(ObjectType.Player);
}
And then to check the types, you can just do:
switch(gridObject.getType()) {
case ObjectType.Player:
// do something
break;
case ObjectType.Monster:
// do something else
break;
case ObjectType.Coin:
// do something else
break;
}
Related
I have read from other sources that it isn't a good idea for objects to know about each other especially the ones on same level. It should be more like hierarchy.
My problem is quite unique as I haven't figured out a way around it. Also I have been unlucky to come across any topic that addresses my issue specifically.
The problem
I am building a chess app and I am constructing the model of the app. Right now I have an abstract objects like for example Piece which other pieces like Queen, Knight and the rest would inherit from.
I also have a Board class which handles all board model and state of a game. Now each of my piece has a generateMove() method to calculate possible moves from their position and to do this they need to know the state of the board. Also the Pieces are been instantiated by Board at startup.
Question
Do I go ahead and instantiate Pieces by e.g
public class ChessBoard{
Boardbit = 64bit
Knight = new Knight(start_position, this)
//calculate
}
and then in Knight class method
public long generateMove(ChessBoard);
If no, what other ways can I go about it?
Making Chessboard to know the Knight and vise versa is not elegant. I agree with you in this point. Kind of sticking with the 'Tell don't ask' rule forces the 'higher level' element, in this case the chessboard, to tell the piece to move while providing all the required information. The Chessboard itself doesn't know which piece is moving (in this case of predicting possible moves for all pieces), but for sure never knows any details about how a piece can move or is allowed to move. This is just one possible solution using sort of Strategy Pattern. (The Visitor or some similar pattern could also be used here):
Main() {
chessboard = new Chessboard()
PiecesCollection = new PiecesCollection(new Knight(KnightStrategy, Color.Black))
chessboard.AddPieces(PiecesCollection)
CollectionOfAllPossibleMoveCollections = chessBoard.CallculateAllPossibleMoves()
Move selectedMove = ShowOrSelectMove(CollectionOfAllPossibleMoveCollections)
chessboard.ExecuteMove(selectedMove)
}
public class Chessboard{
// fields
PiecesCollectionWhite
// where 'PiecesCollectionWhite' is a collection of `Piece`
PiecesCollectionBlack
// where 'PiecesCollectionBlack' is a collection of `Piece`
CurrentlyVisitedPositionsCollection
// where 'CurrentlyVisitedPositionsCollection' is a collection of `Position`
// methods
AddPieces(PiecesCollection, Color)
CallculateAllPossibleMoves(Color) {
CollectionOfPossibleMoveCollections =
FOREACH Piece IN PiecesCollection OF Color
DO Piece.CalculateMoves(this.CurrentlyVisitedPositionsCollection)
return CollectionOfAllPossibleMoveCollections // where 'CollectionOfAllPossibleMoveCollections ' is a collection that holds a collection of `Move` of which each nested collection represents the possible moves of a chess piece.
}
ExecuteMove(Move) {
RemovePieceFromBoardIfNecessary(Move.ToPosition)
}
}
public class Piece
{
// fields
Strategy
Position
Color
// methods
CallculateMoves(CurrentlyVisitedPositionsCollection) {
PossibleMovesCollection = this.Strategy.Execute(CurrentlyVisitedPositionsCollection, this.Position)
return PossibleMovesCollection where `PossibleMovesCollection` is a collection of `Move`
}
}
public class Knight extends Piece
{
ctor(Strategy, Color)
}
public class Stragtegy
{
abstract Execute(currentPosition, allPiecesPositions) : PossibleMovesCollection
}
public class KnightStrategy extends Strategy
{
Execute(currentPosition, allPiecesPositions) {
PossibleMovesCollection = ApplyKnightMoveAlgorithm()
return PossibleMovesCollection
}
private ApplyKnightMoveAlgorithm() : PossibleMovesCollection
}
public class Move
{
Position fromPosition
Position toPosition
}
public class Color
{
Black
White
}
public class Position
{
Color
xCoordinate
yCoordinate
}
This is just a sketch and not a complete example. There is some state information or operations missing. E.g. maybe you would have to store the Color that was moved last on the chessboard.
Since the Chessboard returns all possible moves (information about all currently visited coordinates) you can easily enhance the algorithm by implementing some intelligence to predict the best possible moves from this information. So before the controller or in this case the Main() will call Chessboard.ExecuteMove(Move) it could make a call to PredictionEngine.PredictBestMove(CollectionOfAllPossibleMoveCollections).
Much better is to have method generateMove(boardState), so your Board should call whatever piece you have and pass them the necessary information for such task. It can be used even for some optimization as board can pregenerate some good-to-use structure each round only once and then pass it to all the pieces (like some 2d array).
How can an object inside another object and the first object re-use the code behind the composed object And what is mean by composed object can be determined at run-time?
class Calculator
{
private:
long double operand_1;
long double operand_2;
long double result;
int optr;
int multiplier;
Button One;
//Button Two..
//..through Nine
Button Zero;
}
class Button
{
private:
int x1;
int y1;
int x2;
int y2;
char Label[55];
public:
Button( );
int hit( );
void show( );
void press( );
void select( );
}
I don't know whether I'm going in the right direction or not, I wanted to know the meaning of "composed object can be determined at Run-time?"
Here Button is composed in calculator class
This principle is demonstrated in Effective Java Book as 'Item 16'. I think when it is said "Favor Composition over Inheritance for code reuse", 'Composition' word is used as synonym of 'Containment' or 'association' and not in the spirit of true composition of UML. "Effective Java" by Joshua Bloch, provides good example under 'Item 16'.
In the demo example in above book, instance for containment (Subclass of Set) is passed through constructor and could always be cached outside (by client) breaking the composition. In book's demo as well it is case of containment and not a pure Composition (where composed object is not known outside).
Code reuse can be achieved by two mechanisms namely 'Inheritance (White box)' and 'Containment (Black box)'. In case of black box reuse, we (can) couple the reusable class at run time by assigning an instance of child class against a reference of Abstract base class/ Interface. In principle Inheritance should be used only when there is 'IsA' relationship and we want to use objects interchangeability and obtain the advantages of polymorphic behavior.
In your example though Calculator is using Button, its not expecting dynamic child class instances. But when we say addActionListener(), Button class will be making use of ActionListener by Containment as 'Button Is NOT a Kind of ActionListener" instead Button 'uses' ActionListener.
Here is an example of code reuse by Composition. Observe that instance of List is not known from outside the PackOfCards, but internally PackOfCards is delegating all functionality to Concrete List. When the Object of PackOfCards is destroyed, List also gets destroyed. But here we will not be able to change the concrete List dynamically from outside due to 'composition'.
public class Card {
public enum Suit{SPADE, HEART,DIAMOND,CLUB}
public enum Rank{ACE,QUEEN,KING}// and others
private Suit suit;
private Rank rank;
public Card(Suit suit, Rank rank) {
this.suit = suit;
this.rank = rank;
}
}
public class PackOfCards {
private List<Card> cards;
public PackOfCards() {
cards = new LinkedList<Card>();
}
public Card getCard(int index){
return cards.get(index);
}
public void shuffle(){
Collections.shuffle(cards);
}
// other methods
}
From the perspective of object-oriented best practices, where should I place a variable or method needed in some children of a parent class, but not others?
Ex.
Classes Button, Knob, Lever, and Switch inherit from parent class Device.
Button, Lever, and Switch need a boolean isOn, but Knob does not. Where would you define isOn?
Lever and Switch need a method Throw() that toggles isOn; Button uses isOn but does not use Throw() to handle it. Does this affect your placement of isOn, and where would you define the Throw() method?
The above is purely an example; let's assume that there are distinct properties of each child class that distinguish it and that there are commonalities that make it reasonable to use the inheritence model discussed.
When only a sub-set of sub-classes share functionality, this can be expressed with an interface that contains the methods in question, which is only implemented by the sub-classes that need them.
public interface OnOffable {
boolean isOn();
void toggleOnOff();
void turnOn(boolean is_on);
void turnOn();
void turnOff();
}
class Switch extends Device implements OnOffable...
If one or more of the functions is moderately complicated, you can create a static utility function that helps prevent redundant code. In this example, however, the "complicated-ness" is the need to keep the on-off state.
In this situation, you can create an OnOffableComposer which (my preference) does not implement OnOffable.
And actually, since this particular interface can be completely implemented (meaning it needs no protected or abstract function), it can actually be a "simple" implementation of it:
public class SimpleOnOffable implements OnOffable {
private boolean isOn;
public class OnOffableComposer(boolean is_on) {
turnOn(is_on);
}
public boolean isOn() {
return isOn;
}
public void turnOn(boolean is_on) {
isOn = is_on;
}
public void toggleOnOff() {
turnOn(!isOn());
}
public void turnOn() {
turnOn(true);
}
public void turnOff() {
turnOn(false);
}
}
Here's how it's used:
public class Switch extends Device implements OnOffable {
private final SimpleOnOffable smplOnOff;
public Switch(boolean is_on) {
smplOnOff = new SimpleOnOffable(is_on);
}
public boolean isOn() {
return smplOnOff.isOn();
}
public void turnOn(boolean is_on) {
smplOnOff.turnOn(is_on);
}
public void toggleOnOff() {
smplOnOff.toggleOnOff();
}
public void turnOn() {
smplOnOff.turnOn();
}
public void turnOff() {
smplOnOff.turnOff();
}
}
Although the composer is "simple", this all demonstrates the concept of choosing composition over inheritance. It allows for much more complicated designs than single inheritance allows.
It sounds like the wrong abstraction all around. At the very least, Knob doesn't belong with the others. I might inject a class between Device and the three closely-related devices. Perhaps something like BinaryDevice:
abstract class Device {}
abstract class BinaryDevice : Device {
abstract void Activate();
abstract void Deactivate();
}
class Switch : BinaryDevice {
void Activate() { // activate the switch }
void Deactivate() { // deactivate the switch }
}
// same for Lever, which honestly is really just a Switch with a different styling and may not even need to be a separate object
class Button : BinaryDevice {
void Activate() { // activate the button, then immediately call Deactivate() }
void Deactivate() { // deactivate the button }
}
Knob can also inherit from Device, but at this point there is no common functionality for a Device so it's not clear why that universal common base class is even necessary. As further functionality is added to the various devices there may indeed be common functionality to push up to the base class. Indeed, there are well established refactoring patterns for dealing with generalization like this.
With the classes above, I imagine there would be error handling for trying to invoke an action in an incorrect state. For example, it's difficult to imagine a scenario where a Button would need anybody to call Deactivate() on it, since it de-activates itself. (Though just as a real-life button can become stuck, so too can this one if the action it invokes hangs for some reason.) But in any event even the Activate() and Deactivate() on the other objects would still need to check state. You can't activate a switch that's already active, for example.
The point is, the clarity of an object model starts to make itself more apparent when terminology and real-world modeling is more carefully considered. A lot of times developers try to shoehorn terminology into a handful of common terms in order to maximize their use of things like inheritance, and unfortunately this often results in the wrong abstraction and a confused domain model.
Build your objects as they naturally exist, then look for patterns which can be abstracted into common functionality. Don't try to define the common functionality first and then force objects to fit that mold.
In general, I would say that if an element of a parent class is needed in some but not all of the children then an intermediate parent should be introduced.
When defining an inheritance hierarchy, it's a logical assumption that the children of a parent should share all properties of that common ancestor. This is akin to the way a biological taxonomy would work, and it helps to keep the code clean.
So let's have a look at the objects in your system (we'll use the "is a" relationship to help us figure out the inheritance hierarchy):
Button, Knob, Lever, and Switch
Each of these might indeed be called "Devices", but when we say "devices" most people will probably think of digital devices like phones or tablets. A better word for describing these objects might be "controls" because these objects help you to control things.
Are all objects Controls? Indeed they are, so every object will have Control as a parent in its inheritance hierarchy.
Do we need to further classify? Well your requirements are to have an on/off status, but it does not make sense for every control to have on/off status, but only some of them. So let's further divide these into Control and ToggleControl.
Is every Control a ToggleControl? No, so these are separate classes of objects.
Is every ToggleControl a Control? Yes, so ToggleControl can inherit from Control.
Are all objects properly classified and are all parent attributes shared by all children? Yes, so we're done building our inheritance hierarchy.
Our inheritance hierarchy thus looks like this:
Control (Code shared by all controls)
/ \
/ \
Knob ToggleControl (Code shared by all controls that can also be toggled - Adds isOn)
\
\
Button, Lever, Switch
Now, to the other part of your question:
Lever and Switch need a method Throw() that toggles isOn; Button uses isOn but does not use Throw() to handle it. Does this affect your placement of isOn, and where would you define the Throw() method?
Firstly, "throw" is a reserved word (at least in Java), so using method names that are similar to reserved words might cause confusion. The method might be better named "toggle()".
Button should (in fact it must) use toggle() to toggle it's isOn since it is a togglable control.
I'm trying to create a basic Pacman game in C++ (I'll use Java syntax in this question as this is somewhat easier to demonstrate), but I can't find a good design option.
So far I have 4 classes:
- Monster: Can be subclassed for monster-specific behaviour and contains all logic for the monsters
- Player: Contains player-logic
- Map: Contains a 2d array representing the map. This array specifies which positions are walls or Pacman food
- Game: contains a Player, a Map and a list of Monsters.
To keep it simple:
public class Game {
Player player;
Map map;
ArrayList<Monster> monsters;
public Game() {
player = new Player();
map = new Map();
monsters = new ArrayList<Monster();
monsters.add(new ScaryMonster());
monsters.add(new DumpMonster());
}
public void update() {
player.update();
map.update();
for (Monster monster: monsters) {
monster.update();
}
public void draw() {
map.draw();
player.draw();
for (Monster monster: monsters) {
monster.draw();
}
}
So all I have to do now is to create a Game object and call update() and draw() on it every time. Very simple. But it doesn't work.
Assume I call update() on the player-object and the player (which is the Pacman ofcourse) hits food. In that case, the map-object should get notified of this (and the position) to remove the food from the 2d-array. Assume the player kills a monster, the position of the monster should get changed (the Monster class has a "position field"). And you can imagine a lot more of these situations.
An option would be to pass the map and monster object as parameters in the update() and draw() method of the player object. And to pass the player and monster objects as parameters in the method calls of map. But that surely doesn't sound like a good OO design.
What's a good OO way to solve this? I was thinking about using the Observer pattern (so Game is the subject, player, map and monsters are observers), but that doesn't make any sense: that way the observers will have to let the subject know of any changes, which is obviously not the correct way of using this.
Any tips would be very welcome.
Thank you very much :)
Why don't you try mapping actions?
Every action has a reaction. So let's say the pacman hits food. That's an action, "hitting food", which in turn has a reaction (notifying the map, or the food, or whatever you like) that the food is not there any longer.
Now imagine the pacman hits a monster, that's another action... what would be the reaction to that? Well it might cause the monster to get dead (a call to the BeDeath method :P) or it could cause the pacman to get death... whatever it is it allow you to chain actions to reactions in the game.
That means the logic of the game, the rules would be in the game class, who in addition already knows all the elements needed and can communicate with each one.
Edit: A simple example (very simple, as the game gets more complex you'll need to think better about actions and reactions structure)
public void IGameInfo
{
List<Monster> Monsters {get;}
Pacman Pacman {get;}
Map Map {get;}
}
public void ComputeReactions()
{
foreach (actionChecker in Actions)
{
actionChecker.Check(gameInfo);
}
}
public void ComputeDotEaten(IGameInfo gameInfo)
{
foreach (dot in gameInfo.Map.Dots)
if (pacman.location == dot.location)
dot.MarkEaten();
}
public void ComputeMonsterEaten(IGameInfo gameInfo)
{
foreach (Monster in gameInfo.monsters)
if (gameInfo.pacman.location == gameInfo.monster.location &&
gameInfo.pacman.Invulnerable)
monster.MarkDeath();
else
Game.EndGame();
}
Or if you like you could also map the reactions
public void ComputeDotEaten(IGameInfo gameInfo)
{
foreach (dot in gameInfo.Map.Dots)
if (pacman.location == dot.location)
Reactions["DotEaten"].Execute(dot);
}
Note that for that to work all you reactions must share a common signature (i.e, taking an array of objects that are cast to the expected parameters)
I am new to OOP. Though I understand what polymorphism is, but I can't get the real use of it. I can have functions with different name. Why should I try to implement polymorphism in my application.
Classic answer: Imagine a base class Shape. It exposes a GetArea method. Imagine a Square class and a Rectangle class, and a Circle class. Instead of creating separate GetSquareArea, GetRectangleArea and GetCircleArea methods, you get to implement just one method in each of the derived classes. You don't have to know which exact subclass of Shape you use, you just call GetArea and you get your result, independent of which concrete type is it.
Have a look at this code:
#include <iostream>
using namespace std;
class Shape
{
public:
virtual float GetArea() = 0;
};
class Rectangle : public Shape
{
public:
Rectangle(float a) { this->a = a; }
float GetArea() { return a * a; }
private:
float a;
};
class Circle : public Shape
{
public:
Circle(float r) { this->r = r; }
float GetArea() { return 3.14f * r * r; }
private:
float r;
};
int main()
{
Shape *a = new Circle(1.0f);
Shape *b = new Rectangle(1.0f);
cout << a->GetArea() << endl;
cout << b->GetArea() << endl;
}
An important thing to notice here is - you don't have to know the exact type of the class you're using, just the base type, and you will get the right result. This is very useful in more complex systems as well.
Have fun learning!
Have you ever added two integers with +, and then later added an integer to a floating-point number with +?
Have you ever logged x.toString() to help you debug something?
I think you probably already appreciate polymorphism, just without knowing the name.
In a strictly typed language, polymorphism is important in order to have a list/collection/array of objects of different types. This is because lists/arrays are themselves typed to contain only objects of the correct type.
Imagine for example we have the following:
// the following is pseudocode M'kay:
class apple;
class banana;
class kitchenKnife;
apple foo;
banana bar;
kitchenKnife bat;
apple *shoppingList = [foo, bar, bat]; // this is illegal because bar and bat is
// not of type apple.
To solve this:
class groceries;
class apple inherits groceries;
class banana inherits groceries;
class kitchenKnife inherits groceries;
apple foo;
banana bar;
kitchenKnife bat;
groceries *shoppingList = [foo, bar, bat]; // this is OK
Also it makes processing the list of items more straightforward. Say for example all groceries implements the method price(), processing this is easy:
int total = 0;
foreach (item in shoppingList) {
total += item.price();
}
These two features are the core of what polymorphism does.
Advantage of polymorphism is client code doesn't need to care about the actual implementation of a method.
Take look at the following example.
Here CarBuilder doesn't know anything about ProduceCar().Once it is given a list of cars (CarsToProduceList) it will produce all the necessary cars accordingly.
class CarBase
{
public virtual void ProduceCar()
{
Console.WriteLine("don't know how to produce");
}
}
class CarToyota : CarBase
{
public override void ProduceCar()
{
Console.WriteLine("Producing Toyota Car ");
}
}
class CarBmw : CarBase
{
public override void ProduceCar()
{
Console.WriteLine("Producing Bmw Car");
}
}
class CarUnknown : CarBase { }
class CarBuilder
{
public List<CarBase> CarsToProduceList { get; set; }
public void ProduceCars()
{
if (null != CarsToProduceList)
{
foreach (CarBase car in CarsToProduceList)
{
car.ProduceCar();// doesn't know how to produce
}
}
}
}
class Program
{
static void Main(string[] args)
{
CarBuilder carbuilder = new CarBuilder();
carbuilder.CarsToProduceList = new List<CarBase>() { new CarBmw(), new CarToyota(), new CarUnknown() };
carbuilder.ProduceCars();
}
}
Polymorphism is the foundation of Object Oriented Programming. It means that one object can be have as another project. So how does on object can become other, its possible through following
Inheritance
Overriding/Implementing parent Class behavior
Runtime Object binding
One of the main advantage of it is switch implementations. Lets say you are coding an application which needs to talk to a database. And you happen to define a class which does this database operation for you and its expected to do certain operations such as Add, Delete, Modify. You know that database can be implemented in many ways, it could be talking to file system or a RDBM server such as MySQL etc. So you as programmer, would define an interface that you could use, such as...
public interface DBOperation {
public void addEmployee(Employee newEmployee);
public void modifyEmployee(int id, Employee newInfo);
public void deleteEmployee(int id);
}
Now you may have multiple implementations, lets say we have one for RDBMS and other for direct file-system
public class DBOperation_RDBMS implements DBOperation
// implements DBOperation above stating that you intend to implement all
// methods in DBOperation
public void addEmployee(Employee newEmployee) {
// here I would get JDBC (Java's Interface to RDBMS) handle
// add an entry into database table.
}
public void modifyEmployee(int id, Employee newInfo) {
// here I use JDBC handle to modify employee, and id to index to employee
}
public void deleteEmployee(int id) {
// here I would use JDBC handle to delete an entry
}
}
Lets have File System database implementation
public class DBOperation_FileSystem implements DBOperation
public void addEmployee(Employee newEmployee) {
// here I would Create a file and add a Employee record in to it
}
public void modifyEmployee(int id, Employee newInfo) {
// here I would open file, search for record and change values
}
public void deleteEmployee(int id) {
// here I search entry by id, and delete the record
}
}
Lets see how main can switch between the two
public class Main {
public static void main(String[] args) throws Exception {
Employee emp = new Employee();
... set employee information
DBOperation dboper = null;
// declare your db operation object, not there is no instance
// associated with it
if(args[0].equals("use_rdbms")) {
dboper = new DBOperation_RDBMS();
// here conditionally, i.e when first argument to program is
// use_rdbms, we instantiate RDBM implementation and associate
// with variable dboper, which delcared as DBOperation.
// this is where runtime binding of polymorphism kicks in
// JVM is allowing this assignment because DBOperation_RDBMS
// has a "is a" relationship with DBOperation.
} else if(args[0].equals("use_fs")) {
dboper = new DBOperation_FileSystem();
// similarly here conditionally we assign a different instance.
} else {
throw new RuntimeException("Dont know which implemnation to use");
}
dboper.addEmployee(emp);
// now dboper is refering to one of the implementation
// based on the if conditions above
// by this point JVM knows dboper variable is associated with
// 'a' implemenation, and it will call appropriate method
}
}
You can use polymorphism concept in many places, one praticle example would be: lets you are writing image decorer, and you need to support the whole bunch of images such as jpg, tif, png etc. So your application will define an interface and work on it directly. And you would have some runtime binding of various implementations for each of jpg, tif, pgn etc.
One other important use is, if you are using java, most of the time you would work on List interface, so that you can use ArrayList today or some other interface as your application grows or its needs change.
Polymorphism allows you to write code that uses objects. You can then later create new classes that your existing code can use with no modification.
For example, suppose you have a function Lib2Groc(vehicle) that directs a vehicle from the library to the grocery store. It needs to tell vehicles to turn left, so it can call TurnLeft() on the vehicle object among other things. Then if someone later invents a new vehicle, like a hovercraft, it can be used by Lib2Groc with no modification.
I guess sometimes objects are dynamically called. You are not sure whether the object would be a triangle, square etc in a classic shape poly. example.
So, to leave all such things behind, we just call the function of derived class and assume the one of the dynamic class will be called.
You wouldn't care if its a sqaure, triangle or rectangle. You just care about the area. Hence the getArea method will be called depending upon the dynamic object passed.
One of the most significant benefit that you get from polymorphic operations is ability to expand.
You can use same operations and not changing existing interfaces and implementations only because you faced necessity for some new stuff.
All that we want from polymorphism - is simplify our design decision and make our design more extensible and elegant.
You should also draw attention to Open-Closed Principle (http://en.wikipedia.org/wiki/Open/closed_principle) and for SOLID (http://en.wikipedia.org/wiki/Solid_%28Object_Oriented_Design%29) that can help you to understand key OO principles.
P.S. I think you are talking about "Dynamic polymorphism" (http://en.wikipedia.org/wiki/Dynamic_polymorphism), because there are such thing like "Static polymorphism" (http://en.wikipedia.org/wiki/Template_metaprogramming#Static_polymorphism).
You don't need polymorphism.
Until you do.
Then its friggen awesome.
Simple answer that you'll deal with lots of times:
Somebody needs to go through a collection of stuff. Let's say they ask for a collection of type MySpecializedCollectionOfAwesome. But you've been dealing with your instances of Awesome as List. So, now, you're going to have to create an instance of MSCOA and fill it with every instance of Awesome you have in your List<T>. Big pain in the butt, right?
Well, if they asked for an IEnumerable<Awesome>, you could hand them one of MANY collections of Awesome. You could hand them an array (Awesome[]) or a List (List<Awesome>) or an observable collection of Awesome or ANYTHING ELSE you keep your Awesome in that implements IEnumerable<T>.
The power of polymorphism lets you be type safe, yet be flexible enough that you can use an instance many many different ways without creating tons of code that specifically handles this type or that type.
Tabbed Applications
A good application to me is generic buttons (for all tabs) within a tabbed-application - even the browser we are using it is implementing Polymorphism as it doesn't know the tab we are using at the compile-time (within the code in other words). Its always determined at the Run-time (right now! when we are using the browser.)