July 11th, 2007 - by cpradio

This past week, I have been undergoing a week of rigorous training learning the key differences between .NET 2.0/3.0 and .NET 1.1. For the past two years our company has been working with the 1.1 framework, and is now migrating towards the 2.0/3.0 framework. This week the instructor said something I knew, but was glad to be reminded about. It wasn’t even a .NET oriented question, it was an object oriented question that does not apply to one specific language, but to all OOP (object oriented programming) models in general.

What is the difference between a struct and a class? When should you use a struct versus a class? How do you know?

What is the difference between a struct and a class?
It is simple, structs cannot be inherited from or extended. They can have properties, private variables, methods, and even constructors and deconstructors. Unfortunately, that is where they end in their likeness to classes. Classes on the other hand are extensible and can be inherited.

Finally, it should be mentioned that structs are stored on the stack as a by value type and classes are stored on the heap as a by reference type. What you do need to know is if you copy a struct to another variable, you will now have two copies of the entire struct in the stack, causing a performance hit (depending on the size). For a class, this is not true, the second variable gets stores the address to the original heap location, thus no performance hit.

So when should you use a struct versus a class?
Whenever you do not need extensibility or inheritance. As for the “How do you know?”, you are the architect; during your analysis take into consideration what you might be able to re-use in the future.

The nice thing about classes are their advance functionality. You can extend upon them creating large webs of functional objects and you can use them as a refactoring foothold to make smaller chunks of reusable code (modularization). For example, let’s say you have a class called “Person”. This class contains information such as “First Name”, “Last Name”, “Middle Initial”, “Birth Date”, and “Gender”.

  1. // PHP
  2. class Person
  3. {
  4.   private $firstName;
  5.   private $middleInitial;
  6.   private $lastName;
  7.   private $birthDate;
  8.   private $gender;
  9.  
  10.   public function __construct()
  11.   {
  12.   }
  13. }
  14.  
  15. // C#
  16. using System;
  17.  
  18. namespace MyClasses
  19. {
  20.   public class Person
  21.   {
  22.     private string firstName;
  23.     private string middleInitial;
  24.     private string lastName;
  25.     private string birthDate;
  26.     private string gender;
  27.  
  28.     public Person()
  29.     {
  30.     }
  31.   }
  32. }

Now let’s say you want to extend that class to have “Customers” and “Employees”. You would inherit the “Person” class and extend it with the additional information you want to store. Let’s say the “Customers” class should have an “Account Number”, “Credit Card Number”, “Credit Card Expiration Date”, and “Credit Card Type”. The “Employees” class would have an “Employee ID”, “Email Address”, “Title”, and “Department”. Now if we didn’t use inheritance, all of this extra data would all be in the “Person” class, and that would just look busy.

So here is the Employees and Customers classes:

  1. // PHP
  2. class Customer extends Person
  3. {
  4.   private $accountNumber;
  5.   private $creditCardNumber;
  6.   private $creditCardExpiration;
  7.   private $creditCardType;
  8.  
  9.   public function __construct()
  10.   {
  11.   }
  12. }
  13.  
  14. class Employee extends Person
  15. {
  16.   private $employeeId;
  17.   private $emailAddress;
  18.   private $title;
  19.   private $department;
  20.  
  21.   public function __construct()
  22.   {
  23.   }
  24. }
  25.  
  26. // C#
  27. using System;
  28.  
  29. namespace MyClasses
  30. {
  31.   public class Customer: Person
  32.   {
  33.     private string accountNumber;
  34.     private string creditCardNumber;
  35.     private string creditCardExpiration;
  36.     private string creditCardType;
  37.  
  38.     public Customer(): base()
  39.     {
  40.     }
  41.   }
  42.  
  43.   public class Employee: Person
  44.   {
  45.     private string employeeId;
  46.     private string emailAddress;
  47.     private string title;
  48.     private string department;
  49.  
  50.     public Employee(): base()
  51.     {
  52.     }
  53.   }
  54. }

Now that we have covered inheritance to show how to extend a class, let’s tackle abstraction. Abstraction provides a mechanism to define methods that MUST be created by anything extending it. For example, let’s say the “Person” class wanted to abstract the method to display the “Full Name”. This way the “Customers” class must write it’s own “Full Name” method and so must the “Employees” class.

Due to the abstraction, our “Person” class needs a few changes:

  1. // PHP
  2. abstract class Person
  3. {
  4.   private $firstName;
  5.   private $middleInitial;
  6.   private $lastName;
  7.   private $birthDate;
  8.   private $gender;
  9.  
  10.   public function __construct()
  11.   {
  12.   }
  13.  
  14.   abstract public function FullName();
  15. }
  16.  
  17. class Customer extends Person
  18. {
  19.   private $accountNumber;
  20.   private $creditCardNumber;
  21.   private $creditCardExpiration;
  22.   private $creditCardType;
  23.  
  24.   public function __construct()
  25.   {
  26.   }
  27.  
  28.   public function FullName()
  29.   {
  30.     return parent::firstName . " " . parent::middleInitial . " " . parent::lastName;
  31.   }
  32. }
  33.  
  34. class Employee extends Person
  35. {
  36.   private $employeeId;
  37.   private $emailAddress;
  38.   private $title;
  39.   private $department;
  40.  
  41.   public function __construct()
  42.   {
  43.   }
  44.  
  45.   public function FullName()
  46.   {
  47.     return parent::firstName . " " . parent::middleInitial . " " . parent::lastName . "(" . $this->title . ")";
  48.   }
  49. }
  50.  
  51. // C#
  52. using System;
  53.  
  54. namespace MyClasses
  55. {
  56.   abstract class Person
  57.   {
  58.     private string firstName;
  59.     private string middleInitial;
  60.     private string lastName;
  61.     private string birthDate;
  62.     private string gender;
  63.  
  64.     public Person()
  65.     {
  66.     }
  67.    
  68.     public abstract string FullName();
  69.   }
  70.  
  71.   public class Customer: Person
  72.   {
  73.     private string accountNumber;
  74.     private string creditCardNumber;
  75.     private string creditCardExpiration;
  76.     private string creditCardType;
  77.  
  78.     public Customer(): base()
  79.     {
  80.     }
  81.  
  82.     public override string FullName()
  83.     {
  84.       return base.firstName + " " + base.middleInitial + " " + base.lastName;
  85.     }
  86.   }
  87.  
  88.   public class Employee: Person
  89.   {
  90.     private string employeeId;
  91.     private string emailAddress;
  92.     private string title;
  93.     private string department;
  94.  
  95.     public Emplyee(): base()
  96.     {
  97.     }
  98.  
  99.     public override string FullName()
  100.     {
  101.       return base.firstName + " " + base.middleInitial + " " + base.lastName + "(" + this.title + ")";
  102.     }
  103.   }
  104. }

Now keep in mind that abstract classes can have non-abstract methods, however, you cannot create an instance of this class, it must be inherited.

Finally, interfaces solve the biggest problem with objects. In C# and PHP, you are only allowed to inherit from a single class, however, you can implement an infinite number of interfaces. Interfaces like abstract classes cannot be instantiated, they can only define the method definitions; they cannot actually implement the methods.

  1. // PHP
  2. abstract class Person
  3. {
  4.   private $firstName;
  5.   private $middleInitial;
  6.   private $lastName;
  7.   private $birthDate;
  8.   private $gender;
  9.  
  10.   public function __construct()
  11.   {
  12.   }
  13. }
  14.  
  15. interface FullNameInterface
  16. {
  17.   public function FullName();
  18. }
  19.  
  20. class Customer extends Person implements FullNameInterface
  21. {
  22.   private $accountNumber;
  23.   private $creditCardNumber;
  24.   private $creditCardExpiration;
  25.   private $creditCardType;
  26.  
  27.   public function __construct()
  28.   {
  29.   }
  30.  
  31.   public function FullName()
  32.   {
  33.     return parent::firstName . " " . parent::middleInitial . " " . parent::lastName;
  34.   }
  35. }
  36.  
  37. class Employee extends Person implements FullNameInterface
  38. {
  39.   private $employeeId;
  40.   private $emailAddress;
  41.   private $title;
  42.   private $department;
  43.  
  44.   public function __construct()
  45.   {
  46.   }
  47.  
  48.   public function FullName()
  49.   {
  50.     return parent::firstName . " " . parent::middleInitial . " " . parent::lastName . "(" . $this->title . ")";
  51.   }
  52. }
  53.  
  54. // C#
  55. using System;
  56.  
  57. namespace MyClasses
  58. {
  59.   abstract class Person
  60.   {
  61.     private string firstName;
  62.     private string middleInitial;
  63.     private string lastName;
  64.     private string birthDate;
  65.     private string gender;
  66.  
  67.     public Person()
  68.     {
  69.     }
  70.   }
  71.  
  72.   interface FullNameInterface
  73.   {
  74.     public string FullName();
  75.   }
  76.  
  77.   public class Customer: Person, FullNameInterface
  78.   {
  79.     private string accountNumber;
  80.     private string creditCardNumber;
  81.     private string creditCardExpiration;
  82.     private string creditCardType;
  83.  
  84.     public Customer(): base()
  85.     {
  86.     }
  87.  
  88.     public override string FullName()
  89.     {
  90.       return base.firstName + " " + base.middleInitial + " " + base.lastName;
  91.     }
  92.   }
  93.  
  94.   public class Employee: Person, FullNameInterface
  95.   {
  96.     private string employeeId;
  97.     private string emailAddress;
  98.     private string title;
  99.     private string department;
  100.  
  101.     public Emplyee(): base()
  102.     {
  103.     }
  104.  
  105.     public override string FullName()
  106.     {
  107.       return base.firstName + " " + base.middleInitial + " " + base.lastName + "(" + this.title + ")";
  108.     }
  109.   }
  110. }

There you have it, in this article we learned how to use classes to extend, abstract, and interface your code to make smaller chunks re-usable and extensible.

History:
07/13/2007 11:44 AM
Added information denoting that structs are stored on the stack and classes are stored on the heap — hat tip to Ramjee.

Be Sociable, Share!

4 Responses to “Objects – Why You Should Care About Them”

1 Golgotha

PHP and C# examples!!!

So which is better :)
j/k let’s not go there…

2 Ramjee

J/K,
Very nice post putting down the differences of class/struct.

One thing that you possibly missed out on when to use class/struct is the memory consideration.
A struct is stored on the stack and is always passed by value
Where as a class is on the heap, and is passed by reference.

This difference influences the choice.!

What do you say?

3 cpradio

I complete agree Ramjee, that does make a difference, and I completely forgot to mention it. I will update the article shortly to include that.

4 Mohammad Samini

Thanks a lot.

Share your thoughts...

mulberry sale spyder womens jacket cheap new balance 574 mulberry outlet cheap new balance 574 arcteryx outlet mulberry sale spyder womens jacket mulberry sale spyder womens jacket mulberry outlet mulberry outlet new balance 574

Popular Articles

Top 10 Commentators


Subscribe to this feed! Subscribe by Email!

Random Bits Podcast

You need to download the Flash player from Adobe

Blogs Worth Reading