Library tutorials & articles
A Twisted Look at Object Oriented Programming in C#
Classes, Objects, and Properties
Why program with objects and inheritance?
Simply put, programming with objects simplifies the task of creating and maintaining complex applications. OOP is a completely different way of thinking that differs significantly from the more traditional function driven sequential programming model of old. Programming with objects without inheritance is “object-based” programming. Adding inheritance to objects is “object-oriented” programming. OOP provides built in support for code reuse (inheritance) and support for runtime variations in program behavior (polymorphism). Without attempting to define these terms, OOP at a minimum:
- Simplifies the creation and maintenance of complex applications.
- Promotes code reuse.
- Allows flexibility in runtime program behavior (a very cool feature).
What is OOP?
Well, lets cut right to the point. What the heck is Object Oriented Programming? Answer: It is a whole new way of thinking about programming! It is a way of modeling software that maps your code to the real world. Instead of creating programs with global data and modular functions, you create programs with “classes”. A class is a software construct that maps to real world things and ideas. Think of a class as a blueprint that contains information to construct a software object in memory. Unlike a simple data structure, software objects contain code for both data and methods. The class binds the data and methods together into a single namespace so that the data and methods are intertwined.
Just as you can build more than one house from a single blueprint, you can construct multiple software objects from a single class. Each object (represented by code in memory) is generated from a class and is considered an “instance” of the class. Since each instance of the class exist in separate memory space, each instance of the class can have its own data values (state). Just as multiple houses built from a single blueprint can differ in properties (e.g. color) and have identity (a street address), multiple objects built from a single class can differ in data values and have a unique identifier (a C++ pointer or a reference handle in C#). Got that! Now take and break and re-read this paragraph. When you come back, you can look at some C# code.
What is a class?
A class is a software construct, a blueprint that can describe both values and behavior. It contains the information needed to create working code in memory. When you create an object, you use the information in the class to generate working code. Let’s create a simple program that models a toaster! The toaster is a real life object. The toaster can have state such as secondsToToast and has a behavior, MakeToast(). Here is our first toaster class in C#:
class Toaster1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
Toaster1 t= new Toaster1();
System.Console.WriteLine(t.MakeToast());
System.Console.ReadLine();
}
private int secondsToToast= 10;
public string MakeToast()
{
return "Toasted for "+secondsToToast.ToString()+" seconds.";
}
}
If you execute this program, the output is:
“Toasted for 10 seconds.”
A working toaster yes, but not very useful unless you like 10-second toast <g>.
What is an object?
An object is an instance of a class. A specific class describes how to create a specific object in memory. So the class must contain information about the values and behaviors that each object will implement. You can create an object using the reserved word “new”. In our Toaster1 application, you create a single instance of the Toaster1 class with the call:
Toaster1 t= new Toaster1();
The reference variable “t”, now contains a reference to a unique instance of the Toaster1 class. You use this reference variable to “touch” the object. In fact, if you set the reference variable “t” to null, so that the object is no longer “touchable”, the garbage collector will eventually delete the Toaster1 object!
t= null;
// If "t" contains the only reference to the Toaster1 object, the
object can be garbage collected. (Strictly speaking, if the Toaster1 object
cannot be "reached", it can be garbage collected.)
MakeToast() is a public method of the Toaster1 object so it can be called from outside the class (Main) using the reference variable “t” to touch the object’s behavior:
t.MakeToast();
Since each object exists in a separate memory space, each object can have state, behavior and identity. Our Toaster1 object has identity since it is unique from any other object created from the Toaster1 class:
Toaster1 t2= new Toaster1();
Now there are two instances of the Toaster1 class. There are two reference variables “t” and “t2”. Each reference variable identifies a unique object that exists in a separate memory address. Since each object contains a method MakeToast(), each object has behavior. Finally, each object contains a value “secondsToToast()”. In a sense, each object now has its own “state”. However, the state is the same for each object! This is not a very useful class design. In fact, the Toaster1 class is not a good representation of a real world toaster since the toast time is immutable.
Here is a second run at the Toaster class that demonstrates the use of public “accessors”, get and set methods. This is a standard idiom in OOP. The actual data is declared private (or protected) so that users of the class cannot access the underlying data. Instead, public methods are exposed to the callers of the class to set and get the underlying hidden data values.
Note: The modifiers “private”, “protected” and “public” are access modifiers that control the visibility of methods and data. The compiler will enforce these visibility rules and complain if you say try to touch a private variable from outside the class. “Public” methods and data are visible to any caller. “Private” methods and data are only visible and “touchable” within the class. “Protected” is a special level of access control of great interest to object oriented programmers, but is a subject that must be deferred to the chapter on inheritance. If you don’t declare an access modifier, the method or variable is considered private by default.
using System;
namespace JAL
{
/// <summary>
/// Summary description for class.
/// </summary>
///
class Toaster2
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Toaster2 t= new Toaster2();
t.SetSecondsToToast(12);
Console.WriteLine(t.MakeToast());
Console.ReadLine();
}
private int secondsToToast= 0;
public string MakeToast()
{
return "Toasted for "+GetSecondsToToast().ToString()+" seconds.";
}
// Public Accessor Functions, Get and Set
public bool SetSecondsToToast(int seconds)
{
if (seconds > 0)
{
secondsToToast= seconds;
return true;
}
else
{
secondsToToast= 0;
return false;
}
}
public int GetSecondsToToast()
{
return secondsToToast;
}
}
}
The callers of the class cannot “touch” the secondsToToast variable which remains private or “hidden” from the caller. This idiom is often called “encapsulation” so that the class encapsulates or hides the underlying data representation. This is an important aspect of OOP that allows the writer of the class to change the underlying data representation from say several variables of type int to an array of ints without affecting the caller. The class is a “black box” that hides the underlying data representation. In this new version of toaster, Toaster2, there are two new methods: SetSecondsToToast() and GetSecondsToToast(). If you look at the “setter” method it validates the callers input and sets the value to zero if the callers input is invalid (<0):
public void SetSecondsToToast(int seconds)
{
if (seconds > 0)
{
secondsToToast= seconds;
}
else
{
secondsToToast= 0;
}
}
The “getter” method really does not do much simply returning the private data value “secondsToToast”:
public int GetSecondsToToast()
{
return secondsToToast;
}
What is a property?
C#.NET implements a language idiom called a “property”. In a nutshell, “a property is a method that appears as a variable”. By convention, a property name starts with an uppercase letter. Here is our new version of Toaster that replaces the get and set methods with properties:
using System;
namespace JAL
{
/// <summary>
/// Summary description for class.
/// </summary>
///
class Toaster3
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Toaster3 t= new Toaster3();
t.SecondsToToast= 12; // the property
idiom
Console.WriteLine(t.MakeToast());
Console.ReadLine();
}
private int secondsToToast= 0;
public string MakeToast()
{
return "Toasted for "+secondsToToast.ToString()+" seconds.";
}
// Properties
public int SecondsToToast
{
get {return secondsToToast;}
set
{
if (value > 0)
{
secondsToToast=
value;
}
else
{
secondsToToast=
0;
}
}
}
}
}
Here are the new setter and getter methods as properties:
// Properties
public int SecondsToToast
{
get {return secondsToToast;}
set {
if (value > 0) {
secondsToToast= value;
} else {
secondsToToast= 0;
}
}
}
The reserved word “value” is used to represent the caller’s input. Note the syntax used to call a property. To set a property use:
t.SecondsToToast= 12;
The method set() now appears as a variable “SecondsToToast”. So “a property is a method that appears as a variable”.
Well, congratulations. You have constructed your first real world class in C#. Since this is a hands on tutorial, I strongly urge you to compile the Toaster3 code and experiment.
Related articles
Related discussion
-
Query Tool to Excel using C# and .NET
by BarbaMariolino (1 replies)
-
looking for help on asp
by cladironbeard (2 replies)
-
Socket Programming in C# - Part 1
by graumanoz (23 replies)
-
LINQ in Action
by naser1 (0 replies)
-
Creating a Windows Service in VB.NET
by Templario55 (107 replies)
Related podcasts
-
Object-Oriented Programming in Ruby
In this episode, I talk with Scott Bellware about object-oriented programming in Ruby, and Ruby's object model. This is taken from a private conversation, and the audio quality suffers at times. Much thanks to Scott for allowing this to be released.This episode of the Alt.NET Podcast is bro...
Events coming up
-
Aug
28
St. Louis Day of .NET
St. Charles, United States
Technical conference with be 2 full days of content with over 40 sessions from local and national speakers, with topics such as:•.NET languages: C#, VB.NET•Technologies: WPF, Silverlight, WCF•Development tools: Visual Studio, TFS, Expression Blend
thanks for the useful info
regards
If you have tried developing large extensible business applications where data needs are in the gigabytes if not terabytes in any static OO based programming language, then you are in for a lot of headaches. OOP does not lend itself well to this type of development as so called real world objects do not translate well into OO objects, most so called real world objects in the business world translate to data. This fact is lost on many managers, developers and analysts. Most applications in the real world are business related and not some academic project. I have been privy to many failed projects because of the selection of high level development language invariably they have always been statically typed. The one overlooked programming paradigm that has been neglected because of the OO hype is table or data driven programming. This form lends itself well to business related applications and can be used in conjunction with any programming paradigm but work wonders with a dynamically type languages. It is easily extensible, scalable and can be easily modified without throwing hundreds of users of the network.
As for Interfaces, function overloading, generics, templates, reflection, RTTI, default parameters, adding scripting etc, these are kludges to make a static language do what a dynamic language already does, and done badly at that.
When I first learned OO programming I was primarily excited by code re-use on the object side of the equation. Objects considered as providers of services to other code that acts as a client.
After many years of developing OO application I eventually grew to see the vast web of code dependencies and to realize that every piece of client code is itself serving some other code i.e. tier 1 calls tier 2 calls tier 3 (tier 2 code is being served by tier 3 but is serving tier 1). I realized that my objects provided a great deal of code re-use but what about all the code that used those objects? That is where Interfaces come in. Thanks to an interface all of your code that uses object A can be swapped out to use object B, C, D, or E regardless of the object type and therefore ancestry. Regardless of object implementation.
In another sense, Interfaces are more "fair". If an object can perform the services declared in the interface then it can be used by code that uses the interface. This means no strict binding to particular object hierarchies and that can save a lot of headaches.
Read the article even if you work with OO, give it to people that are just starting OO.
I'd really like to see this article as the core of explaining more OO topics, in the same format.
Workaround:
Save printable page as complete web page.
Edit default.css file in _files subfolder of saved page.
Change the CODE.Pre line to:
CODE.pre {
PADDING-RIGHT: 7pt; PADDING-LEFT: 7pt; WIDTH: 100%; COLOR: #000000; PADDING-TOP: 7pt; BACKGROUND-COLOR: #fbedbb
}
(removes the display:block)
RRIOS:
Thanks for the excellent write up on this concept. It has actually helped quite a bit to give me a better perspective on the subject of Interfaces. I particularly liked your analogy of Royal family vs democracy.
Thanks!
Inheritance is rigid. It´s like being born into the royal family. Sure, you get alot of privileges without doing anything, but you carry all the baggage and stigmas that come with your family name. You can´t JOIN the royal family. You have to be born into it.
Interfaces are democratic. A system that declares an interface is saying "I dont care who you are or how big or small you are: if you agree to these rules you may join the club". Think of your drivers license. The DVM declares an interface and ANYONE can use the road system as long as they stick to the rules (implement the interface).
In programming terms, suppose you are using two systems, in one you have created a Vehicle class and have several child classes like Car, Bicycle, and Bus. In the other you have cooking items, say for a recipe system. You may have classes like Flour, Eggs, Carrot. These two groups of classes have nothing to do with each other.
You create a third point of sale system for a retail store, and you plan to sell among other things, bicycles and flour. Your point of sale system could declare an IRetail interface that defines to other classes what they need to implement in order to participate in the Point of Sales system like Price(), TaxKey() and UPC().
This means you can reuse your Bicycle and Flour classes, just by adding the implementation of the IRetail interface in order to use them in the Point of Sale system. This new system will be capable of handling any kind of object as long as it implements IRetail.
So Interfaces are an advantage to both the system that declares the interface (they dont care what class of object they are handling) and to the classes that implement them (they can participate in any system as long as they agree to the rules).
http://www.jroller.com/page/haruki_zaemon/20031201#adapter_classes
An interface allows a developer, but more specifically a designer, to say "These features must be implemented." It is then up to the developer to work out the details of how to deliver on those features/abilities. It creates a boundary of expectation from other users of the object.
They can say "Oh I i see it implements IInterface, therefore it will definitely have X, Y and Z". It is quite useful when you wnat to implement concepts in multiple objects instead of concrete functionality. For instance, say you had two types of collections one was a tree and one was a jagged array of parent/child IDs (which in many ways is a tree represented another way but they are syntactically different). If you wanted to implement something like "GetParent", you couldn't (well maybe you could, but go with me for the sake of example) implement one generic function for "GetParent" that would work for both the Jagged Array and the Tree. YOu could however have both objects implement an interface, and then have the developer do the syntactic details of returning an items parent.
Anyway, more half baked analogies.
One of the questions that still persists for me, (and something I have never seen a discussion on) is what real benefit Interfaces offer; it seems they offer some, but that it is somewhat limited. Let me give an analogy, in the form of an old joke. An engineer, a phycicist and an economist were on a desert island with a can of pineapple that had survived the boat wreck. Both the engineer and the physicist made multiple attempts using their scientific knowledge to open the can of pineapple, but to no avail. After some time the economist remarked: "This shouldn't be a difficult problem to solve." "Well, tell us", replied the engineer and physicist in unison. Said the economist, " Assume a can opener."
This is what economists do. They make assumptions and think they have contributed something. Is this not like Interfaces, whose job, it appears, is to make policy statements without ever getting around to implementing anything? All the same amount of coding has to be done whether the interface is used or not; in fact there may be considerable duplication of code if minor changes to an implementation are needed. So what has been achieved? Not nearly as much, it seems, as inheritance would offer, were full inheritance of pure methods possible. This is perhaps why an Abstract class seems to be more useful.
I would appreciate anyone who can resolve my perplexity here. I could learn something.
Pretty good article. Its the first time i acutally laughed and smiled while reading your article. Very good read..
There are a few inaccuracies though just to point out...
1.
MyClass c;
c.someMethod()
does not throw a null reference exception. It actually throws a compiletime error "Use of unassigned local variable". In c# variables much be assigned before use or something like that..
2.
array[] = new array[10]
only returns an array of null references if it you are declaring an array of ref type. If it is a value type, the values will be assigned their default values..
and 3.
comparing type compatibility in most cases should use "as" instead of "is" because if you use is before casting the type, you in effect check the type twice, once before the cast, and once during the cast..
Its just an optimisation really..
Other than that, like i said before, best read i have ever had. Learned a few new words too like "gumption". Who would have thought..
This intro to C-Sharp is a very good tutorial, but its only an intro. The naming of variables and methods need to be standardized for easier readability. It also does not cover data driven dynamic web apps.
...it is a good article and Microsoft does advocate clearer naming of Object variables.
It's a shame you never LEARNED proper grammer.
This thread is for discussions of A Twisted Look at Object Oriented Programming in C#.