Friday, April 3, 2009

Encapsulation

Encapsulation

Think of encapsulation as a black box; data is sent to a method, a lot of work goes on using the data, of which you don't know or care about. An output is returned to the caller. That is the process of encapsulation, or information hiding. Let's take a look at the following class:

  1. public class MultiLineString  
  2. {  
  3.   private CollectionBase<string> _lines = null;  
  4.   private bool _allowEmptyLines = false;  
  5.   private static object _lock = new object();  
  6.   
  7.   public bool AllowEmptyLines  
  8.   {  
  9.     get { return _allowEmptyLines; }  
  10.     set { _allowEmptyLines = value; }  
  11.   }  
  12.   
  13.   public int LineCount  
  14.   {  
  15.     get { return _lines.Count; }  
  16.   }  
  17.   
  18.   public string this[int index]  
  19.   {  
  20.     get { return _lines[index]; }  
  21.   }  
  22.   
  23.   public MultiLineString(string text) : this(text, false) { }  
  24.   
  25.   public MultiLineString(string text, bool allowEmptyLines)  
  26.   {  
  27.     _allowEmptyLines = allowEmptyLines;  
  28.     _lines = new CollectionBase<string>();  
  29.   
  30.     if (!allowEmptyLines)  
  31.     {  
  32.       string[] lines = text.Split('\n');  
  33.   
  34.       foreach (string line in lines)  
  35.       {  
  36.         if (line != null)  
  37.           this.Add(line);  
  38.         else if (line == '\r' && this.AllowEmptyLines)  
  39.           this.Add(string.Empty);  
  40.       }  
  41.     }  
  42.   }  
  43.   
  44.   public MultiLineString(StringBuilder builder) : this(builder, false) { }  
  45.   
  46.   public MultiLineString(  
  47.     StringBuilder builder,   
  48.     bool allowEmptyLines) : this(builder.ToString(), allowEmptyLines) { }  
  49.   
  50.   public void AddLine(string line)  
  51.   {  
  52.     if (!this.AllowEmptyLines && string.IsNullOrEmpty(line))  
  53.       throw new ArgumentNullException("line");  
  54.   
  55.     lock (_lock)  
  56.     {  
  57.       _lines.Add(this.TrimLine(line));  
  58.     }  
  59.   }  
  60.   
  61.   public void RemoveLine(int index)  
  62.   {  
  63.     lock (_lock)  
  64.     {  
  65.       _lines.RemoveAt(index);  
  66.     }  
  67.   }  
  68.   
  69.   public override string ToString()  
  70.   {  
  71.     string output = string.Empty;  
  72.   
  73.     foreach (string line in lines)  
  74.       output += line + "\n";  
  75.   
  76.     return output;  
  77.   }  
  78.   
  79.   private string TrimLine(string line)  
  80.   {  
  81.     return line.Trim(new char[] { ' ''\t''\r' });  
  82.   }  
  83. }  

From this class, we see a class that works with multi-line text, ensuring that the new line text is separated by line and retrieved by an index value. The constructor takes astring and parses the initial text. It also allows the adding and removing of lines. However, notice that the base object that stores the lines, the CollectionBase object, is never exposed. Only certain object properties are exposed, but the list isn't directly exposed. This is information hiding, in that we don't need to expose the source object for subscriber to use it, but the subscriber can only use the exposed methods/properties to interact with it.

Why is encapsulation important? Using the above example, it would be really easy to change the underlying source to use a database, XML file, text file, or another data store, without breaking any code that the developer may have created. If the class exposed the list directly, any code that used the list would have to change, replacing it with database code. That makes using this class much harder to maintain and more likely that someone would stay away from using the class. But with the implementation above, nothing is known about the source and so switching the underlying data source is much easier.

This concept is prevalent throughout the .NET framework and any object-oriented development project, as it is important to hide certain information to the consumer of an object, because it aids in maintenance, development, and general use of the object.

No comments:

Post a Comment