Skip to main content
Email Password   helpLost your password?

Introduction

Well, after months of just skimming numerous notes and articles from the Internet about C# and its object-oriented capability, I finally took time to actually sit down, read and understand the topics thoroughly. I discovered how things actually work and learned the meaning of the keywords that are being used. Yeah, I was like a carpenter who has finished studying how hammers and screws work. Well, this deductive learning approach actually paid off because it helped me to really grasp the tenets of object oriented programming, gave me the confidence to actually do a source code walk through without referring to a handbook or a manual and actually think abstractly and see the big picture. In addition, studying the very basic principles behind the general concepts provided me a lot of to think about and opened lots of possibilities to do with C#.

In this article, I will talk about the C# concepts according to how I understood them. I hope you'll enjoy reading and learn something from it.

What is C#?


C# is an object oriented language derived from C++ and is the flagship language of Microsoft's .NET framework. Its intended purpose was to attract software developers to immediately make programs for the .NET framework. The .NET framework is Microsoft's answer to Sun Microsystems' Java, a portable and machine independent platform which was getting popularity among computer users back then and is now very popular software platform among computer users.

For more information about the language's history and rules, please refer to the web.

What is Object Oriented Programming?


Object oriented programming, or OOP, is a paradigm that is centralized around an object's behavior and its relationship with other objects. In this approach, programmers will just have to think abstractly, focus on what objects can do to perform a programming task instead of being meticulous about object's composition and internal functions.

Think of OOP when you think of assembling a ready-to-assemble cabinet. When you order a ready-to-assemble cabinet from Home Depot or IKEA, all the spare parts are ready and all you have to do is assemble the cabinet by finding the parts that link and using the free tools to link them easily. To make things clearer, let's contrast it with the traditional programming approach also using the cabinet assembly example. If in OOP, all you have to do is assemble it, in traditional programming approach, you still have to make the spare parts from scratch and then build the cabinet.

The ease of doing things, definitely, is not the only benefit of OOP. OOP also makes it easier for programmers to compartmentalize everything that composes an application. Say, a programmer can do the user interface and the other programmer can do the software logic. Those two parts can then be easily combined to make the final application by following the OOP standards.

Using OOP, one can also program abstractly or simulate real life objects and scientific concepts. Say, you can translate the concept of bottled water to a C# class, or a bicycle to a C# class, or a moving hand to a C# class, or basically everything to a C# class. See, OOP provides as myriads of possibilities. In the future, maybe programmers will have a complex C# class that represents full human being and can be used to replace the human worker.

Getting to the point


Here's the code that I made after studying C# OOP.

using System;

namespace CSharpOOPExerciseByPaul
{

      class Parent
      {
            public string message;
            protected string customString;

            protected virtual void CustomCode()
            {
                  Console.WriteLine("You made this code.");
            }

            public virtual void baseMethod()
            {
                  Console.WriteLine("From Parent");
            }
      }

      class Son : Parent
      {           
            protected string sonvvv;

            public Son(string str)
            {
                  sonvvv = str;
            }

            public override void baseMethod()
            {
                  base.baseMethod();
                  Console.WriteLine("From Son");
            }
      }
     
      class Grandson : Son
      {
            protected int songgg;

            public Grandson(int kkk): base("Son's constructor")
            {
                  songgg = kkk;
            }

            public override void baseMethod()
            {
                  base.baseMethod();
                  Console.WriteLine("From Grandson");
            }
      }

      class Me : Grandson
      {
            public Me(string str, string msg): base(111111111)
            {
            base.customString = str;
            base.message = msg;
            }

            public static void Main(string[] args)
            {
                  Me paul = new Me("THIS IS A DEMO", "OOP EXAMPLE");         
                  Console.WriteLine(paul.message + "\r\n" + paul.customString + "\r\n" + paul.sonvvv + "\r\n" + "Number from immediate base : " + paul.songgg.ToString());
                  Grandson kkk = new Grandson(1111);
                  kkk.message = "Hi Granny!";
                  Console.WriteLine(kkk.message);
                  paul.baseMethod();
                  paul.CustomCode();
                  Son[] parentArray = new Son[3];

                  parentArray[0] = new Son("LOL");
                  parentArray[1] = new Grandson(666);
                  parentArray[2] = new Me("haha","lol");
                 
                  for (int i = 0; i < 3; i++)
                  {
                        parentArray[i].baseMethod();
                  }

                  Console.Write("Press any key to continue . . . ");
                  Console.ReadKey(true);
            }

            public virtual new void CustomCode()
            {
                  Console.WriteLine("This is the code made by me.");
            }

            public override void baseMethod()
            {
                  base.CustomCode(); //cannot use base(dot) in a static method

                  base.baseMethod();
                  Console.WriteLine("From Me");
            }
      }
}

Well, this is a pretty loaded source code since it contains the defining concepts of OOP.

C#, to be a legitimate object oriented programming language, must satisfy the 3 OOP concepts. And it does. C# has inheritance, encapsulation and polymorphism. The source code above shows us the concepts of inheritance, encapsulation and polymorphism.

The source code, when compiled and run, will just display messages in the console. It may sound useless for most people but the way how the program works is the meat part of the article, which I will unveil now.

Encapsulation


Encapsulation means "data-hiding". It is very important for a component to have the ability to hide data so that a programmer won't be conscious and concerned about them. All he wants to think about is how he can link one object to another to do a programming task. Well, it's kind of a psychological approach. We don't usually mess with the things that we don't see and just work with what we can, right? Since OOP sells itself as something wherein we only concern ourselves of getting results, using those results to get more results and not worrying every process that provide each of the results, C# having the ability to hide data or functions kind of satisfy the encapsulation requisite and is now one step closer to establish itself as a full fledged OOP language.

Here,

      class Parent
      {
            public string message;
            protected string customString;

            protected virtual void CustomCode()
            {
                  Console.WriteLine("You made this code.");
            }

            public virtual void baseMethod()
            {
                  Console.WriteLine("From Parent");
            }
      }

we see that inside class Parent, class members are labeled protected and public. Protected class members are only visible to the parent class and to classes which immediately derive from the parent whereas public class members are visible everywhere. It means that if we are outside and we want to use the class Parent, we can only use it via the message variable and baseMethod() function. In other words, outside classes which don't derive from Parent cannot call the protected function CustomCode() and cannot use the protected variables message and customString but can only call baseMethod() and save strings to message variable.

Well, say class Parent is an iPod. The protected class members can be imagined as the actual electronic spare parts of the iPod, the bits and bytes of the MP3 files saved in the iPod or the process how iPod converts the data to actual music. The public baseMethod() is the Play button and the public message variable is the battery slot of your iPod.

Inheritance


Inheritance is basically passing one's characteristics to other entity. It gives one an ability create an object that contains the same members from other objects. This possibility has useful implications, especially in database programming. For example, we have this database of soldiers and one day, we are assigned to separate the active soldier from the retired ones. Well, to approach that problem, we need to have a new record folder for the retired soldiers. But instead of creating a new database for the retired soldiers from scratch, we can just inherit the database structure from the active soldiers' record folder, since most probably they'll be having the same database structure because of the fact that they are databases of soldiers. All we have to do next is to just customize the new database accordingly.

Take a look at this code.

 class Parent
      {
            public string message;
            protected string customString;

            protected virtual void CustomCode()
            {
                  Console.WriteLine("You made this code.");
            }

            public virtual void baseMethod()
            {
                  Console.WriteLine("From Parent");
            }
      }

      class Son : Parent
      {

      protected string sonvvv;

            public Son(string str)
            {
                  sonvvv = str;
            }
            public override void baseMethod()
            {
                  base.baseMethod();
                  Console.WriteLine("From Son");
            }
      }

      class Grandson : Son
      {
            protected int songgg;
            public Grandson(int kkk): base("Son's constructor")
            {
                  songgg = kkk;
            }

            public override void baseMethod()
            {
                  base.baseMethod();
                  Console.WriteLine("From Grandson");
            }
      }

The listing above shows us that we have a single base class called Parent and derived classes called Son and Grandson. Take note that Grandson derives from Son. The colon (:) operator tells us that the left hand side derives all the properties, fields and functions from the right hand side.

class Grandson : Son

The statement above tells us that all of the class members of Son, which also contains the class members of Parent, are also in the class Grandson. That means that everything from the class Parent are now in the classes Grandson and Son and the underlying factor that defines what can be accessed by what object is the access level (public, private, protected, internal).

To prove take a look at this.

Say I instantiated a Grandson class under the Me class, which is valid in the realms of C#.

    Grandson kkk = new Grandson(1111);
    kkk.message = "Hi Granny!";
    Console.WriteLine(kkk.message); 

Derived class Grandson inherited a public class member message from base class Son, which it got from the base superclass Parent. In other words, message variable remains exposed throughout the inheritance tree.

If you change the message variable in the Parent class to protected, the compiler will throw an error. Why? Because only the current class, in our case the Me class, can only use the properties from classes from which it was derived. It means that when instantiated, Me will contain the inherited non-private properties, fields and functions from Parent, Son and Grandson.

What if say we just want the derived class to call the functions of its base class? Well, things below will give a glimpse of how it is done.

Look at this function,

 protected int songgg;

            public Grandson(int kkk): base("Son's constructor")
            {
                  songgg = kkk;
            }

In this, we have the derived class calling the constructor of its mother or base class.

When the constructor of Grandson (constructor is the method that is executed when the class is instantiated or created in memory) is called, not only it assigns a value to variable songgg but also it calls Son's constructor, a method that accepts a string. sonvvv, which is a class string field in class Son, will contain "Son's constructor".

Polymorphism


Let's imagine the concept of running. A person most probably won't only be running in one place at one time and be doing only the same things while running. A person might be running in a park one day, wearing jogging pants and shirt. That same person might be running across her neighborhood the next day on her jeans, trying to get attention from the cab driver who gave him an excess change. See, wherever that person may be or whatever clothes she wears or her motives are, she's still doing one thing: running. That concept of running remained constant throughout different situations. Or in other perspective, running was used in different occasions. In that sense, the concept of running acquired different forms that suited different scenarios. This is what we call polymorphism.

In C#, polymorphism is possible. It is only possible with inheritance though. A single function can acquire different functionalities throughout the class derivation tree.

Now let's take a look at the source code one more time.

using System;

namespace CSharpOOPExerciseByPaul
{

      class Parent
      {
            public string message;
            protected string customString;

            protected virtual void CustomCode()
            {
                  Console.WriteLine("You made this code.");
            }

            public virtual void baseMethod()
            {
                  Console.WriteLine("From Parent");
            }
      }

      class Son : Parent
      {           
            protected string sonvvv;

            public Son(string str)
            {
                  sonvvv = str;
            }

            public override void baseMethod()
            {
                  base.baseMethod();
                  Console.WriteLine("From Son");
            }
      }
     
      class Grandson : Son
      {
            protected int songgg;

            public Grandson(int kkk): base("Son's constructor")
            {
                  songgg = kkk;
            }

            public override void baseMethod()
            {
                  base.baseMethod();
                  Console.WriteLine("From Grandson");
            }
      }

      class Me : Grandson
      {
            public Me(string str, string msg): base(111111111)
            {
            base.customString = str;
            base.message = msg;
            }

            public static void Main(string[] args)
            {
                  Me paul = new Me("THIS IS A DEMO", "OOP EXAMPLE");         
                  Console.WriteLine(paul.message + "\r\n" + paul.customString + "\r\n" + paul.sonvvv + "\r\n" + "Number from immediate base : " + paul.songgg.ToString());
                  Grandson kkk = new Grandson(1111);
                  kkk.message = "Hi Granny!";
                  Console.WriteLine(kkk.message);
                  paul.baseMethod();
                  paul.CustomCode();
                  Son[] parentArray = new Son[3];

                  parentArray[0] = new Son("LOL");
                  parentArray[1] = new Grandson(666);
                  parentArray[2] = new Me("haha","lol");
                 
                  for (int i = 0; i < 3; i++)
                  {
                        parentArray[i].baseMethod();
                  }

                  Console.Write("Press any key to continue . . . ");
                  Console.ReadKey(true);
            }

            public virtual new void CustomCode()
            {
                  Console.WriteLine("This is the code made by me.");
            }

            public override void baseMethod()
            {
                  base.CustomCode(); //cannot use base(dot) in a static method

                  base.baseMethod();
                  Console.WriteLine("From Me");
            }
      }
}

We can see here that there is a common method that is being declared in all of the classes. In the Parent class, wherein everything is derived, baseMethod() is declared as virtual. Doing so will make it possible for other classes to use it according to its liking and still be called baseMethod().

In the derived class Son,

class Son : Parent
      {
            protected string sonvvv;

            public Son(string str)
            {
                  sonvvv = str;
            }

            public override void baseMethod()
            {
                  base.baseMethod();
                  Console.WriteLine("From Son");
            }
      }

baseMethod() is declared with the word override which means that when Son is instantiated, it instructs the .NET framework to only execute Son's baseMethod() when Son.baseMethod() is called and ignore the baseMethod() in the Parent class. We have to note that technically, there are 2 occurrences of baseMethod() under the class Son.

What if we don't want to override methods and keep 2 distinct coexisting methods with the same name under a single class? Is it possible? The answer is "yes".

If we examine the source code again, we will see that under the Parent and Me classes, we have CustomCode(). Since class Me is derived from class Parent, it means that class Me contains two CustomCode() methods. But still, everything is valid. Why? It is because we've clearly stated that those 2 identical methods should coexist. And we did that by using the keywords "virtual new".

Outroduction


Well, that's all that I've learned from the 2 chapters that I read from a C# text, Programming C# by Jesse Liberty published by O'Reilly in 2003. I hope you at least learned something from it and hopefully made some concepts clearer to you if ever you've been studying OOP and still not getting it..

Revisions

October 07, 2007 - Revised

September 30, 2007 - Original Release


You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralThanks to Paul and everybody! Pin
Schmal
8:52 6 Jan '08  
GeneralTry this Pin
aman.tur
22:15 7 Oct '07  
GeneralBad example Pin
Michael Epner
6:57 5 Oct '07  
GeneralRe: Bad example Pin
paul.amurao
10:26 5 Oct '07  
GeneralBest Book Pin
wallism
3:13 3 Oct '07  
GeneralRe: Best Book Pin
thund3rstruck
8:52 3 Oct '07  
GeneralRe: Best Book Pin
paul.amurao
15:39 3 Oct '07  


Last Updated 6 Oct 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009