Monday, November 7, 2011

- Encapsulation

Class Type:
Is a user defined type composed of field data (member variables) which is the most fundamental programming construct. A class can be added to the project through Project->Add Class (Alt+Shiftr+C) below picture.

Add a class to the project
Objects must be allocated into memory using the new keyword, otherwise you issue compile error.
Field data is usually defined as private of protected , in order to preserve the integrity of your state data, and controlled access usually provided through type properties. You may access to the current class instance through this keyword. However you will issue a compile error if use this keyword in the implementation of a static member as static member operate on class (not object) level.

Constructor:
Constructor is a method in a class which calls implicitly when creating an object using new keyword. It never have return value (even void) and always have a same name as the class. Constructors often validate the incoming arguments to enforce various business rules.

Default Constructor:
Default constructor never takes any arguments. After allocation on the memory default constructor make sure all the field data is  set to a default value based on their type. However you are allowed to redefine the default constructor to suit your needs. Keep in mind if you are not define a default constructor, the C# compiler grants you a default constructor in order to allow the object user to allocated an instance of your type with field data set to the correct default values. However if you define the default constructor C# compiler constructor will be removed from the class silently and is no longer available.

Custom Constructor:
Custom constructor provides a way to initialize the state of an object directly at the time of creation. Constructor arguments number and type (method overloading) make a constructor distinguishable from another.

Master Constructor:
Master constructor is the constructor that takes the greatest number of arguments. A good validation approach is do all required validation logic in master constructor and other constructors can make use of the this keyword to forward the incoming arguments to the master constructor and provide any additional parameters as necessary(or using optional arguments). By this approach all the validation occurs in body of master constructor and remaining constructors body keep empty. Below example shed more light on the issue:

class Person
{
    //Master Constructor include all validation
    Person(string name, string title, int age)
    {
        if (age < 1)
            Age = 1;
        else
            Age = age;
        Name = name;
        Title = title;
    }
    //Custom Constructor get name as argument
    Person(string name)
        :this(name, "", 1){}
    //Custom Constructor get age as argument
    Person(int age)
        :this("", "", 1) { }

    private string Name;
    private string Title;
    private int Age;
}

With help of .NET 4 you can just have one constructor with optional parameter and use the name parameter to invoke the constructor as you wish but keep in mind if you use this approach you can just compile your code in .NET 4 and later .

Static Constructor:
Static Constructor is special type of constructor which is a suitable place to initialize the values of static data when the value is not known in compile time. Here some rules which you need to follow in order to use static constructors:
  • Each class can only have a single static constructor
  • Static constructor does not take any access modifier
  • Static constructor can not take any parameters
  • Static constructor executes before any instance-level constructors.
  • Static constructor will be invoked by runtime when it creates an instance of the class or before assigning the first static member invoked by the caller.
  • Static constructor execute only one time
Why do we need static constructors?
As we know, static members must be invoked directly from the class level and there is no need to create any instance to invoke the static member (commonly found in utility classes). Static members can operate only on static data and call static methods. Static data is allocated once and shared among all objects of the same class category. If we put the initialization of the static field in a normal constructor it will initialize when ever we make a new object, for sure it is not the things that we want. There is two approach in order to initialize a static field only once:
  • One way to setting the a static field is to use member initialization syntax (at declaration )
  • Another way is using static constructor which is helpful when you need to read the static field value form database or external file at runtime.
Static Classes:
Static class can not be created using new keyword and all the members need to be static, otherwise you'll receive compiler errors (helpful in designing utility classes). Example:

 //static class 
static class StaticTime
{
   static private DateTime SpecificTime;
   static private DateTime StartTime;
   //static constructor
   static StaticTime()
   {
       StartTime = DateTime.Now;
   }
   public static void ShowTime()
   {
       Console.WriteLine("Time ShowTime: {0}", DateTime.Now);
       Console.WriteLine("Start Time   : {0}", StartTime);
       Console.WriteLine("Specifc Time : {0}", SpecificTime);
   }
   public static void SetSpecificTime(DateTime my_time)
   {
       SpecificTime = my_time;
   }
}

//main method
static void Main(string[] args)
{
    Console.WriteLine("Time in Main : {0}", DateTime.Now);
    Thread.Sleep(10000);
    DateTime specifc_time = new DateTime(2009, 05, 30, 10, 00, 20);
    StaticTime.SetSpecificTime(specifc_time);
    Thread.Sleep(10000);
    StaticTime.ShowTime();
    Console.ReadLine();
}

Static Class example output
There are tow more alternative ways to prevent the object creation of the class that only exposed static functionality :
  • Define the default constructor as private 
  • Make the class as abstract type. 
The disadvantage of these tow approach is non-static members can be define without any error.

Encapsulation:
Hide object's internal implementation details and preserve data integrity (data protection). In another word encapsulation is the process of hiding unnecessary implementation details from the object user.

Inheritance:
Gives you ability to define a new class definitions based on existing class definitions. Which means you can extend the behavior of a base (Parent) class by inheriting core functionality into the derived subclass (Child). By inheritance we establish "is a" relationship between types.
Good to know under .NET platform, System.Object is always the topmost parent in any class hierarchy.

Containment/delegation model (aka aggregation) or "has a" relationship is another form of code reuse.  Which define member variable of another class and use the functionality.

Polymorphism:
An ability to treat related objects in a similar manner. Polymorphic interface is consist of any number of virtual or abstract members which are available to all descendents. Virtual members are members that defines a default implementation in base class which may override by child class. In contrast abstract methods does not provide any default implementation and child class must override it.

C# Access Modifiers:
Thy are keywords which allow some control access:
  • public : no access restriction
  • private : access only by the class
  • protected : access by the class and it's child
  • internal : accessible only within current assembly
  • protected internal : accessible by current assembly, current class and it's child
By default type members are implicitly private while types are implicitly internal, here is an example:

//The access modifier implicitly set to internal (Type)
class Test
{
    //the access modifier implicitly set to private(Type member)
    Test() { }
}

Non-nested type can only defined as public or internal and if any non-nested type declare as protected or private it will cause compile error.

C# Encapsulation Services:
Concept: An object's internal data should not be directly accessible from an object instance. Rather if the caller wants to alter the state of an object. Changing the state of object can be done indirectly through accessor (getter) and mutator ( setter) alternatively define a .NET property. (black box programming)
Defining public data got one major problem: data itself has no ability to understand whether the current value to which they are assigned is valid with regard to the current business rule of the system.

.NET Properties:
properties are just a simplification for "real" accessor and mutator methods:

private double price;
//The get and set logic is both public, based on the declaration of the property
public double Price
{
    get{return price;}
    set
    {
        if(value < 0)
            Console.WriteLine("Error: price can't be negative");
        else
            price = value;
    }
}

Notice that unlike methods, properties do not make use of parentheses."value" token represent the incoming value used to assign the property  by the caller. By using properties value you may get use the property just like public data, however the encapsulation preserved.

//set
product.Price = 100.00;
//get
double productPrice = product.Price;

Below example shows how properties make the code more readable and easier.

//traditional setter and getter to increment the price by 1
product.setPrice(product.getPrice() + 1);
//using properties
product.Price++;

Common place fro applying the business rule is 'set' portion of the property. Keep in mind a property really map to a get_/set_ pair that's why if you try to declare same method you will issue compile error (e.g set_Price(double price) or double get_Price() for above example).

Property Visibility Control:
The default set and get visibility is controlled by the access modifier of the property declaration. Based on your need you may modify the accessibility levels for get and set logic such as below example:

//product object can only get the itemcode
//however product class and classes derived form it can set the itemCode
public int ItemCode
{
    get{ return itemCode;}
    protected set{ itemCode = value;}
}

Read-Only and Write-Only Properties:
  • Read-Only: omit the set block
  • Write-Only: omit the get block
Automatic Properties:
Automatic properties provides a way for simple encapsulation of field data. Let's say you need just simple assign and return value to easy your task you may use automatic properties as shown in below example:

//Automatic properties:
public class ProductItem
{
    public string ItemName { get; set; }
    public int ItemCode { get; set; }
}

There will be auto-generated private backing filed at compile time which is not visible unless you use tools such as ildasm.exe. But you can't build read-only and write-only automatic properties by omitting set; and get; if you do you'll issue compiler error. However you are allowed to change the access modifier of set and get just like below example: 

//Automatic properties with restriction set and get can be defined as protected
// or private
public class ProductItem
{
    public string ItemName { get; private set; }
    public int ItemCode { get; protected set; }

Good to know auto generated private backing field will be assigned safe default value that can be used directly (null for reference type).

Object Initializer Syntax:
We can initialize an object through object initializer syntax just like following example (default constructor will be invoked behind the scenes). Each member in initialization list maps to the name of a public field or public property of the object being initialized.

//default constructor invoked implicitly
ProductItem product = new ProductItem { ItemName = "My Item", ItemCode = 300 };

//default constructor invoked explicitly
ProductItem product1 = new ProductItem() { ItemName = "My Item1", ItemCode = 301 };

//custom constructor invoked always initializer syntax override the value of constructor
ProductItem product2 = new ProductItem("test", 0) { ItemName = "My Item2", ItemCode = 302 };

Constant:
We can define a constant data with help of const keyword which can never change after the initial assignment.
Constant fields of a class are implicitly static. Assignment must be at time of defining. The value of constant data type must be known at compile time. Example :

public const tax = 0.10;

Read Only Fields:
Read only fields can not be changed after the initial assignment. The deference with constant is the initial assignment of read only fields can be done at runtime (constructor but nowhere else) and they are not explicitly static.

Partial Types:
It been used in order to partition a single class across multiple C# files. For the sake of example, we keep constructor and member of  a class called ProductItme in to the ProdoctItem.cs file and
locate all properties to another file ("ProdoctItemProp.cs") just like following.

//File Name: ProdoctItemPro.cs
public partial class ProductItem
{
    public int ItemCode
    {
        get{ return itemCode;}
        set{itemCode = value;}
    }

    Public string ItemName
    {
        get{return itemName;}
        set{itemName = value;}
    }
}

//File Name: ProdoctItem.cs
public partial class ProductItem
{
    private int itemCode;
    private string itemName;

    public ProductItem(int itemCode, string itemName)
    {
        this.ItemCode = itemCode;
        this.ItemName = itemName;
    }
}

Reference: Pro C# 2010 and the .NET 4 Platform by Andrew Troelsen.

No comments:

Post a Comment