.Net: One Line at a Time

A look at .Net from concepts to deployment.

.Net: One Line at a Time

Making Objects that matter.

In the last article we looked at classes to see if they were as useful as some would say.  Some of the most basic things that object oriented programming gives to a developer, at least on the surface, appear to be just convenience.  They are great and make our lives easier, but can be dealt with in other ways.  I want us to look at just one object oriented concept that takes us beyond useful and really makes objects matter in our development.  So let’s continue with our employee scenario that we looked briefly at last time.  Employees are people as we learned and we saw the use of that.  Now let’s consider it a step deeper.  As the owner of a company you have a wonderful year and want to give a bonus to all your employees.  However managers and workers will not get the same bonus.  How does your application handle it all.  You could have complicated code that would figure out the what type of employee each employee is and then would do something different based on what type the employee is, or you could have polymorphism.  Just the sentence makes it seem like it is going to be so much easier. 

To start let’s take a look at just what polymorphism is.  In keeping with the goal of everything being simple and understandable at any level here is an overly simplistic definition that misses many of the finer points of polymorphism.  Polymorphism allows you to treat a series of classes that have the same base class or interface as the same type of object.  For those of you that want to look deeper into the definition before we get into a code sample, you can look here.  What does this mean for our example though?  Well we have a common base class Employee.  We place a GiveBonus method in Employee as well as each of our subclasses.  When it is time to give bonuses we just call GiveBonus on all employees and it is done.  Of course under the hood there is still the finding out what type it is and doing something different logic.  The wonderful thing is we don’t have to worry about it at all.  Let’s take a look at how it works.

I have added a single method to our Employee class that we use last time.

public virtual void GiveBonus()
{
    Console.WriteLine("If this method runs you don't get a bonus");
}

Mostly this is very similar to what we have already looked at except I have used the word virtual.  In the future we will look at exactly what all we can do with different keywords, but for our sake now putting in that keyword is what allows me to override or change the functionality in derived classes.  I have also created two classes that each derive from Employee. 

public class Manager : Employee
{
    public override void GiveBonus()
    {
        Salary += 10000;
        Console.WriteLine("{0} was given a $10000 bonus",Name);
    }
}

public class Worker : Employee
{
    public override void GiveBonus()
    {
        Salary += 5000;
        Console.WriteLine("{0} was given a $5000 bonus",Name);
    }
}

Again these simplistic classes look a lot like what we have been doing in the past two articles.  The only new thing is the keyword override in each of the methods.  Again a detailed look at the keywords is for future articles, but here is the basic break down.  If you call give bonus on an Employee object you will get the message “If this method runs you don’t get a bonus”.  If you call GiveBonus on a Manager it overrides the Employee functionality and gives a $10000 bonus, and if you call it on a Worker then it will override the Employee functionality with a $5000 bonus.  So as you can see this is really simple code that we did not have to worry with what was going on.  So let’s create some objects and see how hard it is to tell the application which method to call.

List<Employee> employees = new List<Employee>();
employees.Add(new Manager() { Name = "Jimmy", Salary = 100000 });
employees.Add(new Worker() { Name = "James", Salary = 65000 });
employees.Add(new Manager() { Name = "John", Salary = 85000 });
employees.Add(new Worker() { Name = "Jacob", Salary = 45000 });

foreach (Employee emp in employees)
{                
    emp.GiveBonus();
    Console.WriteLine("Your new salary with bonus is {0}",emp.Salary);
}

This code actually has several things that we have not seen so let’s look at it line by line.  First I create a List that will hold Employee objects in it called employees.  This list will only accept Employee objects.  I could not put a Person object in the list because all Employee objects are a Person, but not all Person objects are an Employee.  I am able to put in Manager and Worker objects all that I want.  If you remember back to my last article you will understand that all Manager’s and Worker’s are Employees based on the inheritance listed above.  So I have added two Manager’s and two Worker’s to that List.  So far things are fairly standard and we have a list of all of our Employees.  Let’s try to give them all a bonus.  I have a simple foreach loop that looks at each Employee one at a time and gives them a bonus.  Because of Polymorphism our results are exactly what we would like. 

When we run this application we get the following output.

Jimmy was given a $10000 bonus
Your new salary with bonus is 110000
James was given a $5000 bonus
Your new salary with bonus is 70000
John was given a $10000 bonus
Your new salary with bonus is 95000
Jacob was given a $5000 bonus
Your new salary with bonus is 50000

Notice that we never had to tell it anything about which type of Employee we were working with.  Everything works for us right out of the box because of Polymorphism.  This is certainly not the only benefit of working with classes, but as you can see considering some of the hoops we could have had to jump through we are really in good shape and this code is fully functional out of the box and very simple to create.

Are Classes Really That Useful?

So as we go on the journey of walking through .Net and Object Oriented Programming concepts in general, the common question is how useful are classes.  Unfortunately the answer is not as easy as the question.  Depending on what you are doing and your own mindset you might find that even as a .Net developer you don’t create many classes.  Using classes already developed to aid you in creating your applications really is outside of the scope of the debate on how useful classes are.  You don’t often see someone using an Object Oriented language saying let’s throw out the String class(though you might see them grumble about how it was written).  When it comes to developing your own classes though the argument is wide open with extremes on both ends. 

I have a friend who does driver development for a wireless company.  He really does not care much for Object Oriented Programming.  His biggest complaint is his belief that people are taught that everything needs to be a class.  He recently shared a story about a developer they just hired right out of college that did a data retrieval operation for them and had 7 classes just to represent a single item.  Somewhere in between these two extremes lies the core of what OOP programming is all about and the answer to our question.

Rather than trying to give you my opinion and make you adopt it I want us to take a look at what we can do with classes and let you form your opinions about when and how many classes to use based on the needs that you have.  In another post I looked at objects and how classes are your blueprint for creating an object.  In that post I created a very simple person class to demonstrate an object.  If you are still trying to understand the concept of objects you might want to start with that post here. 

Let’s start by making that class a little more useful.  You probably don’t want to have to manually enter your age all the time.  Not everyone has a job so we probably don’t want to require them to enter a job when creating a person.  We might also like to leave a default constructor in so that a person could be created with no values and then that object could be used to retrieve information from a data source. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ObjectDemo
{
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; private set; }
        public string Job { get; set; }
        public string Weight { get; set; }
        public string Address { get; private set; }
        public DateTime Birthdate { get; private set; }

        public Person()
        {

        }
        public Person(string name, DateTime birthdate)
        {
            this.Name = name;
            this.Birthdate = birthdate;           
        }

        public Person(string name, DateTime birthdate, string job)
        {
            this.Name = name;
            this.Birthdate = birthdate;
            this.Job = job;
        }

        public void CalculateAge()
        {
            int age;
            #region Calculate Age Logic 
            Age = age;
        }

        public void Move(string newAddress)
        {
            this.Address = newAddress;
            #region Forward address logic 
           

        }
    }
}

Ok so we still have a pretty simple class, but at least the point is there on what we could do.  Alone this does not look like much and is just an object but lets look at some other nice features.  Ok we briefly looked at setting a property as read only before.  Now lets consider what that means.  In our class we have logic that can only be changed from within the class.  Also we have methods that though they can be called from outside the class the caller does not know how they work.  This encapsulation allows us to have code that we know is secure.  We can control what is accepted into the Methods and how it is used.  That alone is a huge benefit, but let’s take it even a step further.  We know that our code is secure and someone is not going to be able to mess up how it works.  There is so much more we could do with encapsulation, but there are other benefits to working with classes.  What if we want to work with a person but we need more functionality.  Let’s take this to the next step and say that we want to write an application to monitor our business.  So let’s create a class to handle our employee information.

public class Employee : Person
    {
        public int Salary { get; set; }
        public string Title { get; set; }
        public DateTime HireDate { get; private set; }

        public Employee()
        {           
            Title = "Employee";
            HireDate = DateTime.Today;

        }

        public Employee(string name)
        {
            Name = name;
            Birthdate = DateTime.Today.AddYears(-18);
            Title = "Employee";
            HireDate = DateTime.Today;
        }

    }

 

Again we have a very simple class that would not be very useful in the real world but it serves its purpose for our demonstration.  The first thing to notice is the : Person in the class declaration.  This tells us that it inherits the functionality of the Person class.  What that means is that ever Employee we create is also a person.  Through the first constructor you will notice that the class is pretty standard but then in the second constructor we start seeing inheritance at work.  There is no property for name or birthdate in the employee class but I was able to set both of those because of the fact that an employee is a person.  We have not talked about access modifiers yet but just to make it clear I did have to change the private set; for the birthdate in person so that the employee would have access to it.  You will also notice that the arbitrary setting of age to 18 is pretty useless as well.  In a larger class all of these things would be provided in a useful way.  The ability to encapsulate our data and the use of inheritance really make work as a developer much easier.  That said there are even more powerful uses of classes that we will look at in our next walk through the .Net concepts.

Working with Objects

So you have started the journey into Object Oriented Programming(OOP) and you are ready to see how these objects actually work.  One of the easiest things about OOP is the fact that you can program in the same way that you think.  This is also one of the hardest points for developers trained in non-object oriented languages.  So if you are still wondering what objects are look around.  You are reading a monitor of some sort.  Perhaps there is a phone by you as well.  Maybe you have a calendar on the wall and a picture of your family close at hand.  All of these things are objects.

One very important thing to keep in mind is that all of those objects are real, physical items.  If I am going to the store to buy a calendar for the wall it is not an object it is just an idea.  I know that it will be current and I probably know the size and have a general idea of the style that I like.  Until I actually go to the store and get the calendar I don’t have an actual object though.  Similarly if I am purchasing a phone it is just an idea.  Do I want cordless or am I still in the last century?  How many bases do I want?  Once I purchase the phone though all those properties are set and it is no longer an idea.

The same thing is true in development.  Objects are actual representations of the concept they cover.  For example the concept of a button is well defined.  Buttons have specific abilities and functions.  It is just an idea though when discussed as a button.  When we discuss the back button on this browser we are talking about an actual physical object.  It has a set look and feel based on the browser that you are using and if you click on it you will be taken to the last page that you visited.  That button that you are hopefully not clicking yet is an object.  We commonly call it an instance of a button.  In case you have not figured it out yet pretty much everything is an object.  Each button on the web page is an object.  This web page is an object. 

The power of OOP comes into play not only from the ability to use objects that are already designed like buttons and other controls, but also from the ability to design your own objects.  This is done by creating classes and then creating instances of those classes.  Let’s create a really simple class.  If we want to create a person.  What are some of the things that we know about people.  They will have a name, age, height, weight, address, job and maybe many other properties.  By creating a class we can keep track of this person in one easy to use object.  Keep in mind that we will not have a person object until we actually instantiate the class.   Take a look at the following code and don’t worry too much if you don’t understand everything about it yet.

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Job { get; set; }
        public string Weight { get; set; }
        public string Address { get; private set; }

        public Person(string name, int age, string job)
        {
            this.Name = name;
            this.Age = age;
            this.Job = job;
        }

        public void Move(string newAddress)
        {
            this.Address = newAddress;
            #region Forward address logic
         }
    }

Ok so a simple explanation of what we have.  The class is called Person and it has 5 properties that can be seen or set about a person.  Notice that the Address property has a private set.  Don’t worry too much about it just know that it means that you can only read the address not change it when working with this class.  Then there is a constructor.  This is heart of how to create an object.  This one tells us that we must provide the name, age, and job in order to create a Person object.  The last method that you see is what provides the ability to set an address.  There are many reasons you would limit the ability to change a property.  In this fictional reason we are assuming that we don’t want someone to just change their address because we also want to handle forwarding logic.  This is a really simple example and you would have to use the Move method to even set the address the first time since the constructor did not set anything up.  With this class we don’t actually have an instance yet.  There is no person just the blueprint for how to create a person.  So let’s look at creating a person object.

Person me = new Person("Jimmy", 35, "Developer");
me.Move("My new address");

The first line is all there is to creating a person.  After that line executes there is a Person object named me.  The name, age, and job properties are filled up and I could see them by typing in me and then a . followed by the property that I want to access.  The second line is where we actually use the functionality of a person.  By calling the move method two things happen.  The address property is set to “My new address” and the forwarding logic executes as well.  In this case the logic would just write to the screen “Jimmy you have moved and your new address is: My new address”.  That code is beyond the scope of what we are looking at. 

So you see the basics of working with an object.  In future posts we will look at what you can do with objects and how Object Oriented concepts like inheritance, encapsulation and polymorphism can add power to and simplify the code that you have to write.