Thinking Object Orientedly via Hello World


Introduction

Although I find Object Oriented Programming intriguing, I have not yet been able to form any opinion of it.

This webpage is a simple introduction to the style of thinking involved in developing object oriented programs. It assumes that the reader knows some programming language (not necessarily C) well enough to read code in other languages and get an idea of what's happening.

Reference

For those familiar with some programming language, a good introduction to object oriented programming is Chapter 1 and Appendix B of Damian Conway's Object Oriented Perl. And, should you get sold on the idea of object oriented programming (I am not yet) and like perl, that is the best book that I know of for learning to write object oriented perl.


Hello World in C and C++

    /**
     * File:     hello_world.cpp
     * Author:   Suresh Govindachar
     * Date:     January 20, 2004
     *
     * Purpose:  To code the "Hello World!" program in an Object Oriented way.
     *
     * Description: There are actually three programs (3 main()'s) in this file. 
     *              Each one of the three programs demonstrates one style of coding 
     *              the hello world program:  (1) the usual C way,  (2) a C program 
     *              with an object (partial object orientation),  (3) an object 
     *              oriented way using C++. 
     *
     *              Each program is enclosed within "#ifdef ... #endif" 
     *              pre-processor directives.  So any one of the programs can 
     *              be compiled by defining one (and only one) of the 
     *              following three symbols:
     *
     *                      USUAL_C_HELLO_WORLD
     *                      C_HELLO_WORLD_WITH_AN_OBJECT
     *                      OBJECT_ORIENTED_HELLO_WORLD_USING_CPP
     *
     * Compiling:   The following command was copied into a .bat file as a single
     *              line;  and compilation was done by executing that .bat file:
     *
     *                 c:\opt\mingw\bin\g++ -Wall -o hello_world.exe hello_world.cpp 
     *                      -I c:\opt\mingw\include -L c:\opt\mingw\lib 
     *               
     * Expected Output on the Console:
     *
     *   ______________________________________________________________
     *   With #define USUAL_C_HELLO_WORLD
     *   --------------------------------------------------------------
     *   C:\WINDOWS\COMMAND.COM /c hello_world.exe
     *
     *           Hello World!
     *
     *   Hit any key to close this window...
     *   ______________________________________________________________
     *   With #define C_HELLO_WORLD_WITH_AN_OBJECT
     *   --------------------------------------------------------------
     *   C:\WINDOWS\COMMAND.COM /c hello_world.exe
     *
     *           Hello World From A C-Object!
     *
     *   Hit any key to close this window...
     *   ______________________________________________________________
     *   With #define OBJECT_ORIENTED_HELLO_WORLD_USING_CPP
     *   --------------------------------------------------------------
     *   C:\WINDOWS\COMMAND.COM /c hello_world.exe
     *
     *   You have 2 greeting cards
     *
     *           Default Hello!
     *           (This message cost you $2.5)
     *
     *   Enter customization (such as "From <your name>") for Hello World!: From Suresh
     *
     *           Hello World! From Suresh
     *
     *   You still have 2 greeting cards
     *
     *           Default Hello!
     *
     *   You have 3 greeting cards
     *   You have 2 greeting cards
     *
     *
     *   That was a "Hello World!" From C++OOP Land!
     *
     *   Hit any key to close this window...
     *   ______________________________________________________________
     *
     */
    /* uncomment one and only one of the following */
    //#define USUAL_C_HELLO_WORLD
    //#define C_HELLO_WORLD_WITH_AN_OBJECT
    //#define OBJECT_ORIENTED_HELLO_WORLD_USING_CPP
    #if !(defined(USUAL_C_HELLO_WORLD) || defined(C_HELLO_WORLD_WITH_AN_OBJECT) || defined(OBJECT_ORIENTED_HELLO_WORLD_USING_CPP))
    #error    .Must define one style of coding the hello world program:
    #error    .       USUAL_C_HELLO_WORLD,
    #error    .       C_HELLO_WORLD_WITH_AN_OBJECT, or
    #error    .       OBJECT_ORIENTED_HELLO_WORLD_USING_CPP
    #endif
    //-------------------------------------------
    #ifdef USUAL_C_HELLO_WORLD
    #include <stdio.h>
    int main()
    {
       printf("\n\tHello World!\n\n");
       return 0;
    }
    /*
     * Observe:  The preceding isn't Object Oriented -- in fact,
     *           there is no object in it;  it only has a statement.
     *           So let's try adding an object to it and see if doing 
     *           so will make it "Object Oriented". 
     */
    #endif
    //-------------------------------------------
    //-------------------------------------------
    #ifdef C_HELLO_WORLD_WITH_AN_OBJECT
    /* "Hello World!" with an object */
    #include <stdio.h>
    #include <string.h>
    #define MAX_MESSAGE_LEN (256)  /* a parameter for our object */
    char message[MAX_MESSAGE_LEN]; /* this is our "object" */
    int main()
    {
       sprintf(message, "Hello World From A C-Object!"); /* init the object */
       printf("\n\t%s\n\n", message);                    /* print the object */
       return 0;
    }
    /*
     * Observe:  There is an object in the preceding.  However, in 
     *           thinking about this or other C-programs, one thinks in
     *           terms of a sequence of operations;  and the objects in
     *           C-programs -- no matter how complex a structure they
     *           may be -- are created to help with the sequencing of
     *           operations.  So although we have objects, our
     *           orientation is on the sequence of operations and not on
     *           the objects.  The thought is that we have data and we
     *           want to transform that data into some thing else
     *           (perhaps with or without decisions and/or modifications
     *           based on some other data).  A good characterization of
     *           C-programming would be "imperative programming" (rather
     *           than object oriented programming).   
     */
    #endif
    //-------------------------------------------
    //-------------------------------------------
    #ifdef OBJECT_ORIENTED_HELLO_WORLD_USING_CPP
    /* "Hello World!" in an object oriented way. */
    /*
     * The objects for the Object Oriented "Hello World!" program are
     * going to be Greeting Cards.  Our orientation will be on these
     * objects -- their individual attributes (such as their message, 
     * their cost and whether their message is customizable) and we 
     * will keep track of how many cards we have.  There is also a 
     * generic (default) card.  
     *
     * This Object Oriented version is written in C++. 
     *
     * Observe:  unlike in the preceding (C_HELLO_WORLD_WITH_AN_OBJECT) code, 
     *           the comments here all pertain to the object of interest 
     *           rather than to actions we want-performed/perform.
     */
    #include <iostream.h>
    #include <string.h>
    const int max_message_len = 256;  // a parameter for our cards
    typedef class _GreetingCard   // the abstract data type that specifies the (type of  
    {                             //   data and of operations that form a) greeting card 
      public:                     //   (not exactly, because _count below is a class variable)
        static int _count;        // the number of cards we have (a class variable)
                                  // (note that the preceding variable is exposed -- undesired)
      private:
        char    _message[max_message_len];  // the card's message 
        double  _cost;                      // its cost (negative, if not applicable)
        int     _customizable;              // whether it is customizable (at run time)
      public:
        _GreetingCard()  //constructor:  initialize a generic (default) card
        {
           strcpy(_message, "Default Hello!"); // with a generic (default) message   
           _cost = -1.0;                       // with no cost
           _customizable = 0;                  // uncustomizable
           ++_count;
        }
        ~_GreetingCard() //destructor         // when a card is no longer in use,
        {                                     // decrement the count of the number 
           --_count;                          // cards we have                      
        }
      public:
        int get_count() { return _count; }    // in case we ever need to know how many 
                                              // cards we have
        // the make_greeting_card() methods are various ways of making a greeting card
        void make_greeting_card(char *message = "Default Hello!", double cost = -1.0, int customizable = 0)
        {
           if(strcmp(message, "")) { strcpy(_message, message);}
           if(cost >= 0.0)         {_cost         = cost;}
           if(customizable)        {_customizable = customizable;}
        }
        // Observe:  We would not need the next overloading if the positions of the cost
        // and customization arguments (2 and 3) were switched in the preceding definition.
        void make_greeting_card(char *message, int customizable)
        {
           strcpy(_message, message);
           _customizable = customizable;
        }
        // Finally, here's how our greeting cards greet:  
        //    To greet, they print their message -- if they are customizable, 
        //    they get the customization string before greeting and greet by 
        //    printing their message with the customization appended to it.  
        //    After the greeting, if the card has a cost, it mentions the cost. 
        void do_greet()
        {
           char foo[256];
           strcpy(foo, "\n");
           if(_customizable)
           {
              cout << "Enter customization (such as \"From <your name>\") for " 
                   << _message << ":" << flush;
              cin.get(foo, 255, '\n');
              strcat(foo, "\n");
           }
           cout << "\n\t" << _message << foo; 
           if(_cost > 0.0)
           {
              cout << "\t(This message cost you $" << _cost << ")" << endl;
           }
           cout << endl;
           return ;
        }
    } GreetingCard_t;
    int _GreetingCard::_count=0;  // initialize the number of greeting cards.
                                  // Should be executed before any card has been created
                                  // This line requires _count to be public
    /*
     * In the application, we merely make greeting cards and have them greet.  
     * We do not think -- primarily -- in terms of sequence of actions.  We 
     * think of what we want to create, of what we have and of what we want
     * the things we have to do.
     */
    int main()
    {
       GreetingCard_t hw_gc, def_gc;  // instantiate two greeting cards
       cout << endl;  // add some white space to the output
       cout << "You have " << hw_gc.get_count() << " greeting cards" << endl;
       def_gc.make_greeting_card("", 2.50);  // modify cost of def_gc
       def_gc.do_greet();                    // have it greet
       hw_gc.make_greeting_card("Hello World!", 1);  // modify message and customizability 
       hw_gc.do_greet();                             // have it greet
       cout << "You still have " << hw_gc.get_count() << " greeting cards" << endl;
       {   
          GreetingCard_t hw_gc;   // will be destroyed when this block is exit'ed
          hw_gc.do_greet();       // generic greeting (everything is at default value)
          cout << "You have " << hw_gc.get_count() << " greeting cards" << endl;
       }// card in this block got destroyed automatically
       cout << "You have " << hw_gc.get_count() << " greeting cards" << endl;
       // print the all done message and exit
       cout << "\n\nThat was a \"Hello World!\" From C++OOP Land!\n" << endl; 
       return 0;
    }
    #endif
    //-------------------------------------------


Hello World in object oriented perl

    #!/usr/bin/perl 
    use strict;
    use warnings;
    {
      package GreetingCard;
      #@ISA = ;
      use strict;
      use warnings;
      #cannot have variables such as the next line:
      #my _message="";
      #Example of a class variable
      {
        my $_count = 0;
        sub get_count {$_count}
        my $_increment_count = sub {++$_count};
        sub _decrement_count {--$_count};
        sub make_greeting_card
        {
          my ($class, %arg) = @_;
          $_increment_count->();
          return bless {
                         _message       => $arg{message}       || "Hi There!",
                         _cost          => $arg{cost}          || "",
                         _customizable  => $arg{customizable}  || 0,
                        }, $class; 
          #note that return value is a reference to the "private variables" 
        }
      }
      sub do_greet
      {
        my $class = shift;
        my $foo = "\n";
        if($class->{_customizable})
        {
          print "Enter customization for $class->{_message}:";
          $foo  = <>;
          $foo .= "\n";
          print "\n";
        }
        print "\n\t$class->{_message}".$foo; 
        if($class->{_cost}){print "\t(This message cost you \$$class->{_cost})\n";}
        print "\n";
      }
      # DESTROY is a reserved word -- perl calls this sub automatically
      sub DESTROY
      {
         my $class = shift;
         $class->_decrement_count();
      }
    }
    my $hw_gc = GreetingCard->make_greeting_card(message => "Hello World!", customizable => 1);
       $hw_gc->do_greet;
       print "You have ", GreetingCard->get_count, " greeting cards\n";
       {   
          my $hw_gc = GreetingCard->make_greeting_card(message => "Hello World Inside Block!");
          $hw_gc->do_greet;
          print "You have ", $hw_gc->get_count, " greeting cards\n";
       }
       print "You have ", $hw_gc->get_count, " greeting cards\n";
    my $def_gc = GreetingCard->make_greeting_card(cost => "1.00");
       $def_gc->do_greet;
       print "You have ", $def_gc->get_count, " greeting cards\n";
       #Note: the _decrement_count routine is actually exposed:
       GreetingCard->_decrement_count();
       $hw_gc->_decrement_count();
       $def_gc->_decrement_count();
       print "You have ", $def_gc->get_count, " greeting cards\n";
    #--------------------------------------------------------------
       #Some tutorials present the view that a class variable is created by 
       #     taking any reference and blessing it 
       #But, as Damian Conway points out in his book OOP, it is not good to 
       #     do so;  this is illustrated next. 
       my %foo = (
                    _message       => "The greeting goes here", 
                    _cost          => "10,000,000.00",
                    _customizable  =>  0,
                 );
       my $hand_made = \%foo;
       bless $hand_made, "GreetingCard";
       $hand_made->do_greet;
       #the bad thing about the preceding method for creating hand_made is 
       #    that _count did not get updated:
       print "You (still) have ", $hand_made->get_count, " greeting cards\n";
       exit 0;


Author

Suresh Govindachar (email: <initial><last name><at><yahoo>)


Copyright

Copyright (C) 2004 Suresh Govindachar


Disclaimer

The material provided here is provided as-is without any warranty -- without even the implied warranty of merchantability or fitness for a particular purpose. The author assumes no responsibility for errors or omissions or for any sort of damages resulting from the use of or reliance on the provided material.

 Thinking Object Orientedly via Hello World