12 Replies - 8224 Views - Last Post: 24 February 2010 - 01:08 PM Rate Topic: -----

#1 wellwell   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 23-February 10

New to c# - understanding classes?

Posted 23 February 2010 - 01:40 PM

Hi forum, this is my first post and i would just like to ask the more experienced programmers out how to learn c# classes mor efficient. Started the programming c# a couple of days ago. Gone through loops, if statements, switch and such and just got into classes which i find really hard, does anyone have tips or exercises to get the hang of classes faster.

Thanks in advance.
/salute
wellwell
Is This A Good Question/Topic? 0
  • +

Replies To: New to c# - understanding classes?

#2 MentalFloss   User is offline

  • .
  • member icon

Reputation: 577
  • View blog
  • Posts: 1,500
  • Joined: 02-September 09

Re: New to c# - understanding classes?

Posted 23 February 2010 - 02:23 PM

*
POPULAR

This is a somewhat tricky question. I'll try to answer it best I can.

Think of a class as a blueprint. It explains how to build the actual object you want to work with. You could relate this to perhaps a cookie sheet. With a cookie sheet, there are shaped holes that are filled with dough and cooked. When complete, you have a cookie that is a direct representation (hopefully) of the form in the sheet.

Let's take it a step further and say that a class not only specifies how to build the object but also what behavior and attributes it has. In C# vernacular, behavior is the methods and attributes are the properties. If we think about the cookie sheet example (which is going to fall apart soon), you can imagine that cookie sheet to have such behaviors as RemoveCookie() or RemoveAllCookies(). There may be attributes such as NumberOfCookies or TrayTemperature.

We can infer what these methods do (behaviors), but we don't really care what they actually do. Well, that's complicated - we don't care about it from inside our calling code. We obviously care about it when it's in context to what we're working with. Now, this is the beauty of classes. We are allowed to take a classification of functionality and encapsulate it into a single representation. In standard modular or procedural programming, these methods might be all over the place or might have global scope or might be edited by anything in the application. Classes attempt to create a sort of black box around the logic behind it.

Instead of having to know the class inside out, you just have to be able to reason about its public interface - that is, the attributes and behaviors that are publicly available from your call site.

Let me give you some example:

// This represents a person. If we instantiate this, we will create a brand new person which can be used independent of any person already existing.
public class Person
{
    // This is an attribute of a person. Any person created will have this FirstName attribute. In this case, it is only retrievable.
    public string FirstName
    { get; private set; }

    // This is another attribute of a person. All instantiated Person objects will have this attribute too. Again, read-only.
    public string LastName
    { get; private set; }

    // This is a constructor. Constructors allow us to specify the dependencies a class needs before it can be used or to set attributes to safe values
    // or any number of pre-use operations the class may need. In this case, we just set the passed in attributes to the corresponding attributes of the
    // object
    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }

    // This is a behavior. We can get a representation of this person's first and last name when calling this.
    public string GetFullName()
    {
        return String.Format("{0} {1}", FirstName, LastName);
    }

    // I needed a static example so I used Clone(). This is a common method that is realized through the interface ICloneable.
    // This behavior is different than GetFullName because it does not require an instance of the class. You will see a lot of this in 
    // System.Math and System.Console.
    public static Person Clone(Person person)
    {
        Person p = new Person(person.FirstName, person.LastName);
        return p;
    }
}



So, let's see how we use it a little bit:

public class Program
{
    // Entry point.
    public static void Main()
    {
        // Create a new person and display the information populated by constructor.
        Person person = new Person("Mental","Floss");
        Console.WriteLine("PERSON 1:");
        PrintPerson(person);

        // Create a new person and display the information populated by constructor.
        // Print PERSON 1 again to show that they are two different things.
        Person another = new Person("John", "Doe");
        Console.WriteLine("PERSON 2:");
        PrintPerson(another);
        
        Console.WriteLine("PERSON 1 AGAIN:");
        PrintPerson(person);

        // Usage of static method "Clone":
        Person copy = Person.Clone(another);
        Console.WriteLine("PERSON 2:");
        PrintPerson(copy);
    }

    // Helper method to clean up client code in main a little.
    private void PrintPerson(Person person)
    {
        Console.WriteLine("First Name={0}, Last Name={1}", person.FirstName, person.LastName);
    }
}



If you can imagine that Person class has about 10 other private methods for processing and such, then it makes sense that all of this functionality should be encapsulated into a Person class.

That's the gist of it. Does it make sense? Any questions?

EDIT:
I'm feeling spunky today so I'll do interfaces too. I don't know if you've gotten to them yet, but when you do, hopefully this makes them easier to grasp.

Interfaces are a construct in C# that allow you to specify what a class needs to support in order for it to be considered as qualifying. The best way to think about this is to say that an interface is a class contract. Any class that wants to implement the interface must satisfy the needs of that interface by implementing EVERYTHING on that interface.

Interfaces do not have any implementation of their own. This is left to the implementing class. To really illustrate this, I need an example. So, with our existing Person concept, let's create an AddressBook class. This class is responsible for managing a collection of people.

public class AddressBook
{
    // Here's another constructor.
    public AddressBook()
    {
        // This one does nothing at the moment.
    }
}



OK. That's our skeleton. Let's create that collection.

public class AddressBook
{
    private List<Person> contacts = null;

    // Here's another constructor.
    public AddressBook()
    {
        contacts = new List<Person>();
    }
}



I added some new syntax here that might seem a little scary. There is a collection in the System.Collections.Generic namespace called List<T>. This maintains a collection of any type you specify and only that type you specify. In this case, this list is going to manage Person objects.

Now, the list itself is private so let's add a method to add people:

public class AddressBook
{
    private List<Person> contacts = null;

    // Here's another constructor.
    public AddressBook()
    {
        contacts = new List<Person>();
    }

    public void AddPerson(Person contact)
    {
        contacts.Add(contact);
    }
}



OK. We have a very simple class that will add provided Person objects to its collection.

The stage is set -

Everything's going great but you just found out that your address book should differentiate friends from business associates. Let's create two people that just extend the class Person.

public class Friend : Person
{

}

public class BusinessAssociate : Person
{

}



This way, we can pass both people in to the Add method still because it works on Person. Since both of these classes are Person then, we are fine. Guess what? We can never, ever extend another class now. These classes are locked in on extension. We need a way to say that these two are the same, but without burning our one and only class inheritance.

Let's create that interface I was talking about. We will call it IContact and it will specify the behavior and attributes required to be considered an IContact.

public interface IContact
{
    string FirstName { get; }
    string LastName { get; }
}



Alright. Anything that is IContact MUST implement get properties for FirstName and LastName. Let's update:

public class Friend : IContact
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
}



A Friend is now an IContact. Let's do BusinessAssociate:

public class BusinessAssociate : IContact
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
}



It's the exact same thing.

Let's update that address book so this all makes sense.

public class AddressBook
{
    private List<IContact> contacts = null;

    // Here's another constructor.
    public AddressBook()
    {
        contacts = new List<IContact>();
    }

    public void AddPerson(IContact contact)
    {
        contacts.Add(contact);
    }
}



Notice that I have changed all of the Person entries to IContact. The address book will accept ANYTHING that properly implements IContact interface. It doesn't even have to be a person now. It can be anything as long as it implements IContact.

The special thing about this is that since IContact has FirstName and LastName, we can use it without knowing what an IContact really is.

public class AddressBook
{
    private List<IContact> contacts = null;

    // Here's another constructor.
    public AddressBook()
    {
        contacts = new List<IContact>();
    }

    public void AddPerson(IContact contact)
    {
        contacts.Add(contact);
    }

    public void PrintBook()
    {
        foreach (IContact contact in contacts)
        { 
            Console.WriteLine("First Name={0}, Last Name={1}", contact.FirstName, contact.LastName);
        }
    }
}



That's pretty amazing huh?

There's more to this - such as the various ways to structure these guys in order to have cleaner code, but this is just a taste.

You're on the right track though. Classes, abstract classes, and interfaces are integral to the language so you have to learn them very well.

EDIT:

Quote

Any chance you could just add a bit about abstract classes on top of your excellent article?


Certainly.

Before we think about abstract classes, let's think about what a class is at all. A class is a collection of behaviors and attributes that (hopefully) when taken as a whole represent a single concept.

When this concept requires more specialization, we create a new class that derives from this class. This derived class has special behavior and attributes to it that the more general class can't handle. Both of these are simply still classes.

When the concept requires more generalization, we create a new class which will be derived from our original class. This way, we create a more general set of behaviors and attributes that a family of the original class shares with other classes of that same concept.

What if that more generalized class that we created has to be considered incomplete because each of the deriving classes are all far too specialized? We can't instantiate this class because it's just not usable.

In this case, that generalized class should be changed to an abstract class. With this, we can ensure that our incomplete class is not instantiated while at the same time, the fully constructed deriving classes will be considered the same as that generalized class.

Let's pretend that we have 3 classes: Employee, Supervisor, Administrator.

public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public void PrintName()
    {
        Console.WriteLine("Employee: {0} {1}", FirstName, LastName);
    }
}

public class Supervisor
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public void PrintName()
    {
        Console.WriteLine("Supervisor: {0} {1}", FirstName, LastName);
    }
}

public class Administrator
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public void PrintName()
    {
        Console.WriteLine("Administrator: {0} {1}", FirstName, LastName);
    }
}



Each of these have FirstName and LastName properties. Each of them have one method called PrintName(). This method is special though. As part of the name, it also outputs what the person is (Administrator, Employee, Supervisor).

We have a group of classes with related functionality. So, let's create a super class that these will derive from.

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public void PrintName()
    {
        Console.WriteLine("Person: {0} {1}", FirstName, LastName);
    }
}

public class Employee : Person
{ }

public class Supervisor : Person
{ }

public class Administrator : Person
{ }



OK. That's all well and good, but now our PrintName() method is wrong. We lost the ability to show the type of person it is. Now, there are a lot of other ways to accomplish what we need, but I'm just trying to address abstract classes.

Anyway, Person class could be converted to abstract and the method could be declared as abstract. This way we can let the deriving classes handle what it means to PrintName().

public abstract class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public abstract void PrintName();
}

public class Employee : Person
{
    public override void PrintName()
    {
        Console.WriteLine("Employee: {0} {1}", FirstName, LastName);
    }
}



Here's some client code:

static void Main(string[] args)
{
    Person p = new Employee();
    p.PrintName();
    Console.ReadLine();
}



We create a new Employee, but we use it as a Person. Since Person has PrintName as public abstract, we call PrintName() and it goes to the Employee's implementation of PrintName(). The output is as expected "Employee: [first name] [last name]".

The abstract class can also have implementation. Let's create a new method called GetAge(). We'll need a new property on Person called DateOfBirth.

abstract class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }

    public abstract void PrintName();

    public void PrintAge()
    {
        Console.WriteLine("Age: {0}", GetAge());
    }

    public int GetAge()
    {
        int age = Math.Abs(DateTime.Now.Year - DateOfBirth.Year);

        // Code taken from: http://snippets.dzone.com/posts/show/1632
        if (DateTime.Now.Month < DateOfBirth.Month || (DateTime.Now.Month == DateOfBirth.Month && DateTime.Now.Day < DateOfBirth.Day))
            age--;
        return age;
    }
}



Here's some client code:

static void Main(string[] args)
{
    Person p = new Employee();
    p.FirstName = "Mental";
    p.LastName = "Floss";
    p.DateOfBirth = new DateTime(1981, 10, 4, 4, 0, 0);

    p.PrintName();
    p.PrintAge();
    Console.ReadLine();
}



So, PrintName() is specialized behavior, but PrintAge() is going to be the same no matter what. Regardless, the calling code only knows this object as a Person. It doesn't care what's implemented where.

I hope this makes sense. When you get into abstract classes, a lot of experimenting will help you understand it better.

This post has been edited by MentalFloss: 24 February 2010 - 12:02 PM

Was This Post Helpful? 7
  • +
  • -

#3 eclipsed4utoo   User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1534
  • View blog
  • Posts: 5,972
  • Joined: 21-March 08

Re: New to c# - understanding classes?

Posted 23 February 2010 - 02:33 PM

And to go along with MentalFloss' example, the "PrintPerson" could also do this...

private void PrintPerson(Person person)
{
    string personFullName = person.GetFullName();

    Console.WriteLine("Full Name={0}", personFullName);


    //Console.WriteLine("First Name={0}, Last Name={1}", person.FirstName, person.LastName);
}



Just thought I'd throw this in since MentalFloss didn't use the "GetFullName" method.

This post has been edited by eclipsed4utoo: 23 February 2010 - 02:34 PM

Was This Post Helpful? 3
  • +
  • -

#4 MentalFloss   User is offline

  • .
  • member icon

Reputation: 577
  • View blog
  • Posts: 1,500
  • Joined: 02-September 09

Re: New to c# - understanding classes?

Posted 23 February 2010 - 02:34 PM

Oh yeah - I didn't.
Good update.
Was This Post Helpful? 0
  • +
  • -

#5 cdh   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 37
  • Joined: 19-January 10

Re: New to c# - understanding classes?

Posted 23 February 2010 - 02:43 PM

Can I ask a question in here as well? I'm new too and learning about classes right now as well.

public static Person Clone(Person person)



What exactly is (Person person)? That is confusing to me.

Also you said the static method is different because it doesn't require an instance of the class. Is an instance of the class,

FirstName = firstName;
        LastName = lastName


If so then it seems to me that
(person.FirstName, person.LastName)


is in instance of the class. If not then I guess I don't understand what an instance of the class is?
Was This Post Helpful? 0
  • +
  • -

#6 MentalFloss   User is offline

  • .
  • member icon

Reputation: 577
  • View blog
  • Posts: 1,500
  • Joined: 02-September 09

Re: New to c# - understanding classes?

Posted 23 February 2010 - 02:53 PM

Quote

Can I ask a question in here as well? I'm new too and learning about classes right now as well.
public static Person Clone(Person person)


What exactly is (Person person)? That is confusing to me.


C# is case-sensitive. I basically exploited that here by just naming the parameter the same as the class and only differing in case. This makes them different. Person is the class and person is the instance of that class. In terms of methods, this is what's known as a method parameter. Methods that take parameters are passed in those parameters in the calling code. For example:

Person copy = Person.Clone(somePerson);



This invokes the static method Clone() on the class Person (which does not require an instance) by passing in an existing person. The method then returns an instance of a Person. Since we can see both sides of the code, we know that the person passed in has their attributes copied to a new person and that new person is what's returned. This leaves somePerson untouched and copy to have the same values as somePerson.

Quote

Also you said the static method is different because it doesn't require an instance of the class. Is an instance of the class,

FirstName = firstName;
LastName = lastName



Yes, those are instance members. FirstName and LastName are both properties of an instantiated Person. If the properties were static (which is possible), then you would access them via Person.Property. The assignment is taking what's passed in from the constructor (which is called to create the class) and assigning them to those properties.

Quote

If so then it seems to me that
(person.FirstName, person.LastName)


is in instance of the class. If not then I guess I don't understand what an instance of the class is?


That's correct. The instance here is "person". This code is accessing the FirstName and LastName properties of that instance.

So, back to that clone method:

public static Person Clone(Person person)
{
    Person p = new Person(person.FirstName, person.LastName);
    return p;
}



The method IS static - yes. However, we are passing an instance of the Person class into the method. So, when we access FirstName and LastName, it's on that passed in existing object (which technically can be null... I just didn't check for it).

Hope that all makes sense.
Was This Post Helpful? 4
  • +
  • -

#7 Lava79   User is offline

  • D.I.C Head

Reputation: 11
  • View blog
  • Posts: 145
  • Joined: 31-January 10

Re: New to c# - understanding classes?

Posted 23 February 2010 - 08:54 PM

@ MentalFloss You explain things very well. As a beginner also, I can usually pick up the concept a lot better after reading your explanation of it, as opposed to just slogging thru my book and attempting to make sense of it. Maybe it's the way you break the sections down. Who knows. But I definitely dig it.

@ eclipsed4utoo You also do a nice job of adding and clarifying as well.


You both pretty much rock. :tup:
Was This Post Helpful? 0
  • +
  • -

#8 MentalFloss   User is offline

  • .
  • member icon

Reputation: 577
  • View blog
  • Posts: 1,500
  • Joined: 02-September 09

Re: New to c# - understanding classes?

Posted 23 February 2010 - 09:12 PM

Quote

You explain things very well.


Thank you.

Quote

As a beginner also, I can usually pick up the concept a lot better after reading your explanation of it, as opposed to just slogging thru my book and attempting to make sense of it.


Thank you again. I know how tedious it can be to read texts and I've read a lot. When it comes to articulating the knowledge, I try to frame it from the perspective I would have appreciated from the books I've read. The down side to this is that sometimes details can be missed that would have been addressed in a text. Again, thank you.
Was This Post Helpful? 0
  • +
  • -

#9 Adkins   User is offline

  • D.I.C Addict
  • member icon

Reputation: 66
  • View blog
  • Posts: 560
  • Joined: 27-October 09

Re: New to c# - understanding classes?

Posted 24 February 2010 - 02:15 AM

If you have gripes about the books you have read (as we all do) and you have a knack for articulating your thoughts into ways that are appealing to your audience why not write your own book? If you do I expect a free version since I gave you the idea :P
Was This Post Helpful? 0
  • +
  • -

#10 batesy3k   User is offline

  • D.I.C Regular

Reputation: 41
  • View blog
  • Posts: 299
  • Joined: 10-September 09

Re: New to c# - understanding classes?

Posted 24 February 2010 - 04:55 AM

Any chance you could just add a bit about abstract classes on top of your excellent article? :)
Was This Post Helpful? 0
  • +
  • -

#11 MentalFloss   User is offline

  • .
  • member icon

Reputation: 577
  • View blog
  • Posts: 1,500
  • Joined: 02-September 09

Re: New to c# - understanding classes?

Posted 24 February 2010 - 12:05 PM

Quote

Any chance you could just add a bit about abstract classes on top of your excellent article?


Yes. I edited the original post. Hope you like it.
Was This Post Helpful? 0
  • +
  • -

#12 CupcakePirate   User is offline

  • New D.I.C Head

Reputation: 6
  • View blog
  • Posts: 19
  • Joined: 14-February 10

Re: New to c# - understanding classes?

Posted 24 February 2010 - 12:56 PM

View Postcdh, on 23 February 2010 - 12:43 PM, said:

Can I ask a question in here as well? I'm new too and learning about classes right now as well.

public static Person Clone(Person person)



What exactly is (Person person)? That is confusing to me.



Would it be incorrect to say that 'person' is an object created with the attributes and methods of the 'Person' class? So in other words I've created a Person named person?
(Just want to make sure I'm understanding it correctly myself)
Was This Post Helpful? 0
  • +
  • -

#13 MentalFloss   User is offline

  • .
  • member icon

Reputation: 577
  • View blog
  • Posts: 1,500
  • Joined: 02-September 09

Re: New to c# - understanding classes?

Posted 24 February 2010 - 01:08 PM

Quote

Would it be incorrect to say that 'person' is an object created with the attributes and methods of the 'Person' class? So in other words I've created a Person named person?
(Just want to make sure I'm understanding it correctly myself)


Sort of. We're saying that this method takes a person object but it may not be instantiated yet. It's possible it's null. However, when it's not null, what's passed in is an instance of the Person class. So, yes then it would have all of the attributes and behaviors provided by the Person class.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1