ตอน 16 : Class


ไปหน้าแรก | สารบัญ | Laploy.comระเบียนบทความ | บทความจากลาภลอย

เว็บไซต์นี้เป็นตัวอย่างเนื้อหาบางตอนในหนังสือ "เรียนรู้ด้วยตนเอง OOP C# ASP.NET" ครอบคลุม บทที่ 1 ถึงบทที่ 6 (ในหนังสือมี 21 บท) เนื้อหาใน Blog อาจอาจแตกต่างจากในหนังสือเพราะเป็นเนื้อหาที่ยังไม่ได้ตรวจแก้ขัดเกลา (edit)

กดที่นี่เพื่อดูรายละเอียดเนื้อหาในแต่ละบท

กดที่นี่เพื่อไปยังเว็บบอร์ด ถาม-ตอบ 

 

 

Class

การนิยามคลาสก็คือการสร้าง type ใหม่ การสร้าง type เป็นเรื่องสำคัญที่สุดเรื่องหนึ่งในการเขียนโปรแกรมภาษา C# ภาษาอื่นๆ ที่เป็นภาษา OOP อย่าง C++ C# และ Java ล้วนสนับสนุนให้ผู้นักเขียนโค้ดสร้าง type กันทั้งสิ้น ภาษาที่มิใช่ OOP อย่างภาษา C ไม่มีคลาส มีแต่ struct ซึ่งคล้ายคลาสมาก การสร้าง struc ในภาษา C# ก็ถือเป็นการสร้าง type เช่นเดียวกับคลาส (ดูหัวข้อถัดไปเรื่อง struct)

ดังนั้นการออกแบบและสร้าง type จึงเป็นหน้าที่หลักอย่างหนึ่งของ “กรรมกรซอฟท์แวร์” (software developer)

คลาสคล้าย struct มากจนเกือบเป็นฝาแฝด ข้อแตกต่างที่สำคัญมีเพียงประการเดียวคือ struct เป็น value type ส่วนคลาสเป็น reference type ข้อแตกต่างนี้ทำให้สิ่งที่เราสร้างจากคลาสมีภาวะเป็น object (คือเป็น reference type) ส่วนสิ่งที่เราสร้างจาก struct จะมีภาวะเช่นตัวแปรสามัญ (คือเป็น value type)

หากจะนิยามว่า struct คือกลไกที่เอื้ออำนวยให้นักเขียนโปรแกรมสร้าง data type แบบใหม่ขึ้นได้ เราก็ต้องนิยามว่าคลาสคือกลไกที่เอื้ออำนวยให้นักเขียนโปรแกรมสร้าง object แบบใหม่ขึ้นได้

ในภาษา C# โค้ดสำหรับสร้างคลาสเรียบง่ายมาก ดูตัวอย่าง

class Class1
{
     int foo = 1;
}

โค้ดมีเพียงสามบรรทัดแต่ก็ถือเป็นคลาสที่สมบูรณ์ บรรทัดแรกคำว่า class เป็น keyword ของภาษา C# ทำหน้าที่บอกว่าต่อไปนี้เป็นนิยามของคลาส คำว่า Class1 คือชื่อคลาสที่ผู้เขียนตั้งขึ้นเอง จะตั้งเป็นอย่างอื่นก็ได้ บรรทัดถัดมาเครื่องหมายวงเล็บปีกกาเปิด { ทำหน้าที่บอกให้รู้ว่าไส้ใน (body) ของคลาสจะเริ่มจากตรงนี้ บรรทัดที่สาม int foo = 1; เป็นการสร้างตัวแปรชนิด int หนึ่งตัวและกำหนดค่าเริ่มต้นให้มันด้วย ตัวแปรตัวนี้ถือเป็นตัวแปรที่เป็น “สมาชิก” ของคลาส Class1 คลาสอื่นไม่สามารถเรียกใช้งานได้ เพราะภาษา C# หากไม่ระบุขอบเขต (access modifier) ของสมาชิก ตัวแปลภาษาจะจะกำหนดให้เป็น private โดยอัตโนมัติ ตามปรกติเราจะเรียกตัวแปรที่สมาชิกแบบ private ของคลาสว่า data field

นี่เป็นตัวอย่างคลาสอย่างสั้นที่สุด ซึ่งใช้ประโยชน์อะไรไม่ได้มาก หากจะให้เป็นคลาสที่ทำงานได้อย่างมีประโยชน์ต้องเพิ่มโค้ด เพิ่มสมาชิกของคลาสให้มากกว่านี้ สิ่งต่างๆ รายการต่อไปนี้สามารถถูกนำมาใช้เป็นสมาชิกของคลาสได้

  • Constructors
  • Destructors
  • Constants
  • Fields
  • Methods
  • Properties
  • Indexers
  • Operators
  • Events
  • Delegates
  • Classes
  • Interfaces
  • Structs

 

Base class / Derived class

คลาสที่มีคลาสอื่นนำไปใช้สืบสันดานเรียกว่า base class คลาสที่สืบสันดานจากคลาสอื่นเรียกว่า derived class โปรดพิจารณาตัวอย่างโค้ดต่อไปนี้

class TestBase
{
     int foo = 1;
}

class TestDerived : TestBase
{
     int bar = 2;
}

ผู้เขียนสร้างนิยามคลาสสองคลาส คลาสแรกชื่อ TestBase ทำหน้าที่เป็น base class ส่วนคลาส TestDerived ทำหน้าที่เป็น derived class โปรดสังเกตว่า base class ก็เหมือนคลาสธรรมดาทั่วไป ไม่มีอะไรเป็นพิเศษ ส่วน syntax การกำหนด base class ต้องทำตรงส่วนประกาศของ derived class ในตัวอย่างข้างบนคือ TestDerived : TestBase นั่นคือหลังการประกาศชื่อคลาสใส่เครื่องหมาย colon (ทวิภาค : คือเครื่องหมายจุดคู่ที่เห็นทางซ้าย) ตามด้วยชื่อคลาสที่ต้องการนำมาใช้เป็น base class สำหรับคลาสนี้

ในภาษา C# คลาสทุกคลาสเป็น derived class ทั้งนั้น ในตัวอย่างโค้ดข้างบน คลาส TestDerived เป็น derived class เพราะสืบสันดานจาก base class ชื่อ TestBase ส่วนคลาส TestBase เราไม่ได้ระบุ base class C# complier จะถือว่า base class คือ object อันเป็นคลาสที่นิยามไว้ใน namespace System ให้ทำหน้าที่เป็น base class ของคลาสทุกๆ คลาสใน .NET Framework

 

class implicit type conversion

การแปลงชนิดข้อมูลโดยนัย (implicit type conversion) จะเกิดขึ้นระหว่าง base class และ derived class เมื่อนำไปใช้งาน โปรดพิจารณาโค้ดตัวอย่างดังนี้

1 static void Main(string[] args)
2 {
3      TestBase myBase = new TestBase();
4      TestDerived myDerive = new TestDerived();
5      TestBase myConver = new TestDerived();
6      TestDerived myTest = new TestBase();
7 }

โค้ดข้างบนอิงจากคลาสสองคลาส ที่นิยามไว้ในโค้ดตัวอย่างก่อนหน้านี้ โค้ดบรรทัดที่ 3 และ 4 เราสร้าง instance ของ object จากคลาสตรงกับ type ของ object ยกตัวอย่างเช่น บรรทัดที่ 3 เราสร้างตัวแปรชื่อ myBase ให้มี type เป็น TestBase จากนั้นสร้าง instance โดยใช้คำสั่ง new และเรียก constructor ของคลาส TestBase

สิ่งที่น่าสนใจคือบรรทัดที่ 5 เราสร้างตัวแปรชื่อ myConver มี type เป็น TestBase จากนั้นสร้าง instance โดยใช้คำสั่ง new และเรียก constructor ของคลาส TestDerived สามารถทำได้อย่างไม่มีปัญหาด้วยอานิสงส์ของคุณสมบัติ class implicit type conversion ในภาษา C#

โปรดสังเกตว่า implicit type conversion ทำได้จาก base class ไป derived class เท่านั้น ไม่ใช่กลับกัน ในตัวอย่างโค้ดข้างบน คำสั่งบรรทัดที่ 6 เมื่อคอมไพล์แล้วจะเกิด error มีข้อความว่า

Cannot implicitly convert type TestBase to TestDerived

ท่านจะได้เรียนการประยุกต์ใช้งานคลาสโดยละเอียดในภาคสองในหนังสือเล่มนี้

 

หนังสือ The C Programming Language เป็นงานเขียนคลาสสิก เป็นคัมภีร์ภาษาซีฉบับดั้งเดิม เขียนโดยไบรอัน คาร์นิกัน และ แดนนิส ริชชี บิดาแห่งภาษาซี หนังสือเล่มนี้ให้คำจำกัดความของ struc และ union เป็นครั้งแรกในต้นตระกูลภาษาซี

 

stuct

struct คือชนิดข้อมูลที่ผู้ใช้นิยามขึ้นเอง (User defined type) ยกตัวอย่างหากผู้เขียนต้องการเขียน

โปรแกรมเพื่อเก็บข้อมูลสินค้า โดยมี ชื่อสินค้า ขนาด และ ราคาสินค้า ผู้เขียนอาจสร้าง struct ดังต่อไปนี้

struct Product

struct Product
{
     string ProductName;
     int Size;
     double Price;
}

โค้ดข้างบนนี้ทำหน้าที่สร้าง struct ซึ่งมีสมาชิกสามตัว คำสั่งบรรทัดแรกคำว่า struct เป็น keyword ในภาษา C# ทำหน้าที่บอกให้รู้ว่านี่คือนิยามของ struct คำว่า Product เป็นชื่อ struct ซึ่งเป็นชื่อที่ผู้เขียนตั้งขึ้นเอง บรรทัดที่สามผู้เขียนสร้างตัวแปรสมาชิกเป็น string ชื่อ ProductName เพื่อทำหน้าที่เก็บชื่อสินค้า บรรทัดต่อมา int Size ทำหน้าที่สร้างตัวแปรสมาชิกแบบ int เพื่อเก็บขนาดของสินค้า บรรทัดที่ห้า double Price ทำหน้าที่สร้างตัวแปรสมาชิกเพื่อเก็บราคาสินค้า

การจับตัวแปรที่เป็นเรื่องเดียวกันสามตัวมารวมไว้เป็นก้อนเดียวกันอย่างนี้ คำในวิชา OOP เรียกว่าการทำencapsulation เราสามารถสร้าง instance ของ struct ได้โดยใช้คำสั่งดังตัวอย่างนี้

Product A = new Product();

Product B = A;

โค้ดบรรทัดแรกสร้างตัวแปร A ซึ่งมี type เป็น Product (คือ struct ที่นิยามไว้ข้างบน) บรรทัดที่สองสร้างตัวแปรชื่อ B ให้มี type เป็น Product เช่นเดียวกัน และในค่าที่อยู่ภายใน A มาใส่ B ท่านคงสังเกตว่าทั้ง A และ B แม้จะคล้าย object อย่างยิ่งแต่ก็ไม่ใช่ เพราะมันมีต้นกำเนิดมาจาก struct และ struct ทั้งหลายล้วนเป็น value type ซึ่งมีที่พำนักใน stack ทั้งนั้น ซึ่งจะไม่ได้รับการข้องแวะจาก Garbage Collector แต่อย่างใด

ในตัวอย่างข้างบน ทั้ง A และ B เป็นข้อมูลสองชุดต่างหากจากกัน หากเราแก้ไขค่าของ A ค่าของ B จะไม่ได้รับผลกระทบ ในทำนองเดียวกันหากเราแก้ไขค่าของ B ค่าของ A จะไม่เปลี่ยนแปลง

ดูราวกับ struct เป็นเพียงสิ่งที่หลงเหลือมาจากภาษา C เพราะเอกสาร MSDN (Microsoft Development Network) แนะนำให้ทำทุกอย่างด้วยคลาส และใช้ struct เท่าที่จำเป็นจริงๆ เท่านั้น เช่น หาก type ที่ท่านกำลังคิดจะนิยามเป็น type ที่มีสมาชิกน้อย และมีช่วงชีวิตสั้น และมักฝังตัวอยู่ภายใน object ตัวอื่น อาจเป็นการดีหากสร้างมันจาก struct

ทั้งคลาสและ struct เราต้องเป็นผู้ตั้งชื่อมันและสมาชิกทุกตัวของมัน ต่อไปนี้เป็นแนวทางที่จะช่วยให้ท่านตั้งชื่อสิ่งต่างๆ ได้ดีขึ้น

ตอนต่อไป : หลักการตั้งชื่อในภาษา C#

Post a comment or leave a trackback: Trackback URL.

ใส่ความเห็น

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Google+ photo

You are commenting using your Google+ account. Log Out / เปลี่ยนแปลง )

Connecting to %s

%d bloggers like this: