OOP C# Syntax #1: Class

       เพื่อให้เห็นภาพ ผมเลยเอาบทนี้ขึ้นก่อนมิฉะนั้นมันจะมีแต่ทฤษฎีจะงงกันใหญ่ Class คือผลผลิตของสองแนวคิดครับ แนวทาง ADT และ แนวทาง Object มาสรุปรวมตัวกันเป็น class  

using System;
class Producer
{
	private int w;
	public static int x;
	public int y;
	private static int z;
	private void world(int x)
	{
	}
	public Producer(int number)
	{
	}
	private static void func()
	{
	}
                public void func3()
	{
	}
	public static void func2()
	{
	}
}	

       อย่างที่บอกว่า class เป็นเพียงแค่แบบพิมพ์เขียว เวลาที่คุณใช้จริงๆ คุณต้องสร้างมันเป็น Object ดังนี้

 

class Consumer
{
	public static void Main()
	{ 	Producer p;
		p = new Producer(15);
	}
}

เรามาดูกันนะครับว่าพอเริ่มทำงานก่อนการทำงานบรรทัดแรก โปรแกรมจะจองเนื้อที่อะไรบ้าง

class.jpg (22128 bytes)

ก่อนที่ผมจะอธิบาย เรามาตกลงกันเรื่องความหมายของสัญลักษณ์ก่อน

    รูปข้างบนแสดงให้เห็นว่าเมื่อเราเริ่ม run program ก่อนที่โปรแกรมจะทำงานเป็นบรรทัดแรกมันมีการจองที่อย่างไรบ้าง เราจะเห็นได้ว่า ตัวแปรหรือ function ที่จองนั้นเป็นตัวที่มี modifier เป็น static ทั้งสิ้น พูดอีกอย่างได้ว่าตัวแปร/function ที่เป็น static นั้นจะถูกสร้างทันทีเมื่อเวลาสร้าง class ซึ่งก็ก่อนการ run program หรือพูดได้อีกอย่างว่า ตัวแปร/function static เป็น ตัวแปร/function ของ class

    เมื่อสร้าง class ทั้งสองได้แล้ว เราสังเกตว่าที่ class Producer นั้น มีตัวแปรที่มองเห็นได้จากภายนอกคือ x และ มี function ในลักษณะเดียวกันชื่อว่า func2() ส่วนใน Consumer ก็มี function Main() เมื่อเริ่มทำงานนั้น .Net จะมองหาว่า Class ไหนมี Main() ซึ่งก็เจอที่ Consumer เลยเริ่มเรียก Run จากที่นั่น เมื่อเริ่ม run Main() เรามาดูกันว่า ใน Main มีอะไร

public static void Main()
{ 	
   Producer p;
   p = new Producer(15);
}

บรรทัดแรกสั่งให้จองตัวแปรที่ชื่อว่า p เป็น reference สำหรับ instance ของ Producer ตัวแปรตัวนี้มีขนาดตายตัวครับ ไม่ใหญ่น่าจะประมาณ 8 bytes เอาไว้เก็บตัวชี้ที่ชี้ไปยัง object เมื่อเริ่มต้นบรรทัดแรก p นี้ยังไม่ได้ชี้ไปไหน ดังนั้นมันจึงเป็น null ครับ

คำสั่งที่สอง คำสั่ง new() เป็นคำสั่งที่ให้สร้าง object ใหม่ ชนิด Producer ซึ่งส่ง 15 เข้าไป ตัว Constructor จะทำงาน รายละเอียดตรงนี้ เดี๋ยวเราค่อยมาดูกัน เมื่อทุกอย่างเรียบร้อย มันจะ return ค่า address ของ object นั้นคืนออกมา ซึ่งเราก็เอา p ไปรับ ดังนั้น p จึงชี้ไปที่ object ใหม่ด้วยประการฉะนี้

reference.jpg (19013 bytes)

   ผลลัพธ์จากสองคำสั่งนั้นจะเป็นตามรูปข้างบนครับ คุณจะเห็นได้ว่า ตัวแปร p นี้ reference ไปยัง instance ของ class Producer เราใช้ศัพท์คำว่า "instance ของ class" แทนคำว่า object เพราะ คำว่า "instance ของ class Producer" ให้เรารู้ว่า object นี้ถูกสร้างมาจาก class Producer นั่นเอง

    คุณจะสังเกตได้ว่าตัวแปร/function ที่ไม่ได้ประกาศเป็น static จะมาที่ object ตัวนี้ทั้งหมด แต่ตัวแปร/function ที่เป็นสีส้มนั้น ไม่ได้มาเลย เรียกใช้ก็ไม่ได้นะครับ มันแยกเป็นสองส่วนจริงๆ ตัวแปร/function เรียกว่ามันเป็นของ class ส่วนสีชมพูเราเรียกว่าเป็นของ object หรือ instance ครับ

    ในที่นี้ ตัวแปร w และ function world(int) นั้นเป็น private ภายนอกจะเรียกใช้ไม่ได้ เราเรียกได้เฉพาะ y และ func3() เท่านั้น

    ผมตกไปอย่างหนึ่งครับคือ function ที่เป็นสีฟ้า คุณสังเกตนะครับ function นี้หน้าตามันแปลกประหลาดจากคนอื่น คือมันไม่มี Return type ไม่มีแม้กระทั่งเป็น void และที่สำคัญคือมันชื่อเดียวกับ class ลักษณะนี้เราเรียกว่า Constructor ครับ หมายถึงเป็นผู้สร้าง สร้างอย่างไรเรามาดูกัน คือ function นี้เราเราใช้เองไม่ได้นะครับ มันจะถูกเรียกโดยอัตโนมัติ เมื่อมีคำสั่ง new() เท่านั้น เมื่อมีการเรียกคำสั่ง new หลังจากจองที่ทุกอย่างได้เรียบร้อยแล้ว function นี้จะถูกเรียกครับ เพื่อให้ programmer มาเขียนเพิ่มเติมก่อนจะไปทำบรรทัดต่อไป ส่วนมากก็คือเอาไป init ค่าตัวแปรต่างๆ นั่นแหละครับ สาเหตุที่มี constructor ก็เพื่อให้ object มันสมบูรณ์ในตัว พอ new() มาจะได้ใช้งานได้เลย

    Constructor มีได้หลายตัวนะครับต่อหนึ่ง class มันขึ้นอยู่กับว่าตอน new() คุณส่ง parameters มาเป็นอะไรบ้าง มันจะตรวจสอบดูแล้วเลือก Constructor ที่มี parameters ตรงกับที่เราส่ง จำได้ไหมครับว่าลักษณะแบบนี้เราเรียกว่า function overload เราจึงพูดได้ว่า Constructor สามารถ overload ได้

คราวนี้เรามาลองดูต่อครับ สมมุติว่า ใน Main() มีสี่คำสั่งดังนี้

public static void Main()
{ 	
   Producer p;
   p = new Producer(15);
   Producer q;
   q = p;
}

    สองคำสั่งแรกเหมือนเดิม ดังนั้นจะได้ภาพตามข้างบน ส่วนสองคำสั่งที่เหลือนั้น คำสั่งแรกเป็นคำสั่งที่สร้างตัวแปร reference ไปยัง instance ของ class Producer อีกตัวหนึ่งคือ q ซึ่งมันยังไม่ชี้ไปที่ใดเลย มันจึงมีค่าเป็น null

    คำสั่งสุดท้ายไม่ได้สร้าง object ใหม่นะครับ จำได้ไหมครับ การสร้าง object นั้นจะสร้างเมื่อพบคำสั่ง new() เท่านั้น q = p; นี้ เป็นการบอกว่า q จะชี้ตำแหน่งเดียวกับ p ดังรูปนี้ครับ

reference2.jpg (20666 bytes)

    จะเห็นได้ว่า object ยังคงมี object เดียวแต่มีตัวชี้สองตัว นั่นหมายความว่า ถ้า p เปลี่ยนค่าอะไร q ก็จะเปลี่ยนตาม แต่พูดอย่างนั้นก็อาจไม่ถูกนัก ที่จริงต้องพูดว่า p และ q ชี้ไปที่ตำแหน่งเดียวกัน ดังนั้นเมื่อ p เปลี่ยนค่าอะไรก็จะกระทบไปที่ q ด้วยเช่นกัน

แล้วถ้า Main() เป็นแบบนี้หละ

public static void Main()
{ 	
   Producer p;
   p = new Producer(15);
   p = new Producer(20);
}

   ผมคงไม่วาดรูปให้ดูแล้วนะครับ ในบรรทัดที่สอง p ชี้ไปยัง object ส่วนในบรรทัดที่สามนั้นเป็นการสร้าง object ใหม่ แล้ว ก็ให้ p ชี้ไป ดังนั้นมันจึงมีสอง object นะครับ p เคยชี้ที่ object แรกแล้วเปลี่ยนเป็น object ที่สอง ทำให้ object แรกไม่มีใครชี้มันจะตายไปครับโดย Garbage Collector ซึ่งจะมีรายละเอียดในบทต่อๆ ไป