Polymorphism #4: Reuse Method of .Net

    บทนี้เรามาเรียนอะไรเกี่ยวกับ .Net บ้างดีกว่า ในบทนี้ผมจะแนะนำคุณถืง Polymorphism ที่ .Net Library ประยุกต์เอามาใช้ ผมจะเริ่มต้นที่ class object(หรือ Object ก็เป็นตัวเดียว) ก่อน class ไดๆ ก็ตามที่เราใช้ใน C# ไม่ว่าเราจะสร้างขึ้นเอง หรือว่าเป็น Library ของ .Net เองก็ตาม มันแอบ inherit มาจาก class object ดังนั้น ไม่ว่า class ใดๆ ก็ตามสามารถ ใช้ตัวชี้ชนิด object มาชี้ได้ ดังตัวอย่างต่อไปนี้

class Employee
{
}
class Start
{
	public static void Main()
	{
		Employee em1 = new Employee();
		Employee em2;
		object obj;
		obj = em1;
		em2 = (Employee)obj;
		int x = 5;
		object obj2 = x;
	}	
}

    จาก Code นี้เราจะเห็นได้ว่า เราสามารถ cast ชนิด Employee ให้เป็น object ได้ หรือแม้แต่ int ที่เป็น value type ก็ทำได้เช่นกัน (ทำได้ผ่านการ boxing ถ้าคุณยังจำได้)

    ใน class object นี้เอง มี virtual Methods อยู่ 4 ตัวที่เป็น public  ซึ่งมันจะ inherit ไปยังทุก class ซึ่ง C# ใช้งานทั้ง 4 methods ตามเวลาที่เหมาะสม ซึ่งสี่ตัวนี้มีการ declare ดังนี้

   public virtual bool Equals(object)

        ตัวนี้ถูกออกแบบมาเพื่อจัดการปัญหาในการเปรียบเทียบ object สองตัว ผมจะเริ่มให้ดูถึงปัญหาก่อน

equals.cs

using System;
class Employee
{
	private string name;
	public Employee(string name)
	{
		this.name = name;
	}
}
class Start
{
	public static void Main()
	{
		Employee x = new Employee("Supoj Choachaicharoenkul");
		Employee y = new Employee("Supoj Choachaicharoenkul");
		Employee z = x;
		if (x == y)  {
			Console.WriteLine("True");
		} else {
			Console.WriteLine("False");
		}
	}	
}

DOS Prompt

C:\CS>equals
False

C:\CS>_

    ที่มัน False เพราะว่าถ้าคุณใช้ == เปรียบเทียบ มันไม่ได้เปรียบเทียบเนื้อหาใน object นะครับว่าเหมือนกันหรือไม่ แต่มันเปรียบเทียบว่า ตัวชี้ทั้งสองตัวนี้ชี้ตำแหน่งเดียวกันหรือไม่ ดังนั้นถ้าเปรียบเทียบ z กับ x จะได้ true ครับ นอกนั้นทุกคู่ได้ false หมด แล้วเราจะแก้อย่างไร ในเมื่อเรารู้ว่าถึงแม้ x และ y เป็นคนละ object แต่ว่ามันเก็บชื่อเดียวกัน ทางแก้เราก็ทำการ override Equals Method มา แล้วเอามาใช้แทน == ดังนี้ครับ

equals2.cs

using System;

class Employee
{
	private string name;
	public Employee(string name)
	{
		this.name = name;
	}
	public override bool Equals(object x)
	{
		Employee temp = (Employee)x;
		if (temp.name == this.name) {
			return true;
		} else {
			return false;
		}
	}
}
class Start
{
	public static void Main()
	{
		Employee x = new Employee("Supoj Choachaicharoenkul");
		Employee y = new Employee("Supoj Choachaicharoenkul");
		Employee z = x;
		if (x.Equals(y))  {
			Console.WriteLine("True");
		} else {
			Console.WriteLine("False");
		}
	}	
}

DOS Prompt

C:\CS>equals2
True

C:\CS>_

public virtual string ToString()

    ตัวนี้แหละครับเป็นความลับของ System.Console.WriteLine() ว่ามันรองรับ object ทุกตัวโดยที่ตัวมันเองไม่ต้องโดนแก้เลยได้อย่างไร มันทำอย่างนี้ครับ ถ้าคุณส่ง object ใดๆ เป็น paramerter มันจะมองหา Method ToString() เพื่อเอาค่าที่คุณอยากแสดงจาก object ไปแสดง แต่ถ้าคุณไม่ได้ override ไว้ มันจะแสดงชื่อ class ของคุณ (มันก็ run code ใน virtual method นั่นแหละ) ดูตัวอย่างครับ

tostring.cs

using System;
class Employee
{
	private string name;
	int age;
	public Employee(string name, int age)
	{
		this.name = name;
		this.age = age;
	}
}
class Start
{
	public static void Main()
	{ 		
		Employee supoj = new Employee("Supoj Choachaicharoenkul", 30);
		Console.WriteLine("Wow!!! {0}", supoj);
	}
}

DOS Prompt

C:\CS>tostring
Wow!!! Employee

C:\CS>_

    ถ้าเราต้องการให้ WriteLine() พิมพ์คำว่าอะไร เราก็ override ToString() แล้ว return ค่านั้นออกไปเลยดังนี้

tostring2.cs

using System;
class Employee
{
	private string name;
	int age;
	public Employee(string name, int age)
	{
		this.name = name;
		this.age = age;
	}
	public override string ToString()
	{
		return "Name: " + this.name + ", Age: " + age.ToString(); 
	}
}
class Start
{
	public static void Main()
	{ 		
		Employee supoj = new Employee("Supoj Choachaicharoenkul", 30);
		Console.WriteLine("Wow!!! {0}", supoj);
	}
}

DOS Prompt

C:\CS>tostring2
Wow!!! Name: Supoj Choachaicharoenkul, Age: 30

C:\CS>_

public virtual int GetHashCode()

    เรื่องนี้มันจะซ้ำซ้อนกับที่ผมจะเขียนเรื่อง Hashing เอาไว้รอตอนผมเขียนเรื่องนั้นดีกว่า

 public Type GetType()

    Method นี้ยังยุ่งยากเกินความเข้าใจ เอาไว้ให้ถึงบทที่เกี่ยวข้องก่อน แล้วผมจะขยายให้ฟัง