สํารวจโพลีมอฟิฟิสที่ใช้สืบทอดกัน
โพลีมอฟิฟิกที่ใช้การสืบทอดนั้นยึดตามลําดับชั้นของคลาสที่คลาสสืบทอดลักษณะการทํางานและคุณสมบัติจากคลาสพื้นฐาน ความสัมพันธ์แบบสืบทอดจะช่วยให้คุณสามารถจัดการกับออบเจ็กต์ของคลาสที่ได้รับมาเป็นออบเจ็กต์ของคลาสพื้นฐาน การที่ถือว่าออบเจ็กต์คลาสที่ได้รับมาเป็นออบเจ็กต์คลาสพื้นฐานช่วยให้คุณสามารถเขียนโค้ดที่ทํางานกับออบเจ็กต์หลายชนิดโดยไม่ทราบชนิดเฉพาะในเวลาที่คอมไพล์
ตัวอย่างโค้ดต่อไปนี้แสดงให้เห็นถึงโพลีมอฟิฟิกแบบอิงตามการสืบทอดใน C#:
// Base class
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("The animal makes a sound.");
}
}
// Derived class Dog
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("The dog barks.");
}
}
// Derived class Cat
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("The cat meows.");
}
}
// Derived class Cow
public class Cow : Animal
{
public override void MakeSound()
{
Console.WriteLine("The cow moos.");
}
}
class Program
{
static void Main()
{
// Create an array of Animal objects
Animal[] animals = new Animal[3];
Animal animal1 = new Dog();
Animal animal2 = new Cat();
Animal animal3 = new Cow();
animals[0] = animal1;
animals[1] = animal2;
animals[2] = animal3;
// Demonstrate polymorphism
foreach (Animal animal in animals)
{
animal.MakeSound();
}
}
}
ในโค้ดตัวอย่างนี้ โปรดสังเกตว่าคลาส Program จะสร้างอาร์เรย์ของออบเจ็กต์ Animal และกําหนดอินสแตนซ์ของ DogCatและ Cow ไปยังองค์ประกอบอาร์เรย์ มีการเรียกใช้เมธอด MakeSound บนแต่ละวัตถุในอาร์เรย์ โดยแสดงโพลีมอฟิฟิก วิธีการ MakeSound ถูกแทนที่ในชั้นเรียนที่ได้รับมาเพื่อให้พฤติกรรมที่เฉพาะเจาะจงสําหรับสัตว์แต่ละชนิด
แปลงออบเจ็กต์ของคลาสฐานเป็นคลาสที่ได้รับมา
การคัดเลือกใน C# คือกระบวนการในการแปลงวัตถุชนิดหนึ่งเป็นอีกชนิดหนึ่ง การคัดเลือกมักจะใช้เมื่อใช้งานพอลิมอฟิกโดยใช้ลําดับชั้นการสืบทอดซึ่งคุณมีระดับชั้นฐานและคลาสที่สืบทอดมาอย่างน้อยหนึ่งประเภท
การหล่อมีสองประเภทหลัก:
การคัดเลือกโดยนัย: จะเกิดขึ้นโดยอัตโนมัติเมื่อแปลงคลาสที่ได้รับมาเป็นคลาสพื้นฐาน ซึ่งจะปลอดภัยเนื่องจากทุกอินสแตนซ์ของคลาสที่ได้รับมานั้นเป็นอินสแตนซ์ของคลาสพื้นฐานด้วย
BankAccount account = new CheckingAccount();การคัดเลือกแบบชัดเจน: ต้องใช้ตัวดําเนินการ Cast และใช้เมื่อแปลงคลาสฐานเป็นคลาสที่ได้รับมา ซึ่งไม่ปลอดภัยเสมอไปเนื่องจากไม่ใช่ทุกอินสแตนซ์ของคลาสฐานคืออินสแตนซ์ของคลาสที่ได้รับมา
CheckingAccount checkingAccount = (CheckingAccount)account;
แปลงวัตถุโดยใช้คําสําคัญ is และ as
ใน C# คุณสามารถแคสต์ออบเจ็กต์โดยใช้คํา is สําคัญ และ as ได้ คําหลักเหล่านี้เป็นวิธีที่ปลอดภัยในการตรวจสอบชนิดของวัตถุก่อนที่จะแคสต์ไปยังประเภทอื่น ต่อไปนี้เป็นวิธีทั่วไปในการส่งออบเจ็กต์ใน C#:
ใช้คําสําคัญ
isที่มีการจับคู่รูปแบบ:if (account is CheckingAccount checkingAccount) { // Use checkingAccount as a CheckingAccount }- ไวยากรณ์นี้จะตรวจสอบว่า
accountเป็นชนิดCheckingAccountหรือไม่ - หากการตรวจสอบเสร็จสมบูรณ์ ระบบจะแปลง
accountเป็นCheckingAccountและกําหนดให้กับตัวแปรcheckingAccount - วิธีการนี้เป็นไปอย่างรัดกุมและปลอดภัยเนื่องจากเป็นการผสมผสานการตรวจสอบชนิดและการส่งในขั้นตอนเดียว
- ไวยากรณ์นี้จะตรวจสอบว่า
การใช้คําสําคัญ
isตามด้วย casting อย่างชัดเจน:if (account is CheckingAccount) { CheckingAccount checkingAccount = (CheckingAccount)account; // Use checkingAccount as a CheckingAccount }- ไวยากรณ์นี้จะตรวจสอบว่า
accountเป็นชนิดCheckingAccountหรือไม่ - หากการตรวจสอบเสร็จสมบูรณ์ ระบบจะแปลง
accountเป็นCheckingAccountและกําหนดให้กับตัวแปรcheckingAccount - วิธีการนี้เป็นแบบอย่างละเอียดมากกว่าไวยากรณ์การจับคู่รูปแบบ แต่ให้การควบคุมกระบวนการคัดเลือกได้มากขึ้น
- ไวยากรณ์นี้จะตรวจสอบว่า
การใช้คําสําคัญ
as:CheckingAccount checkingAccount = account as CheckingAccount; if (checkingAccount != null) { // Use checkingAccount as a CheckingAccount }- ไวยากรณ์นี้จะพยายามส่ง
accountไปยังCheckingAccountและกําหนดผลลัพธ์เป็นcheckingAccount - หากแคสต์สําเร็จ
checkingAccountประกอบด้วยวัตถุหล่อ มิฉะนั้นจะเป็น null - วิธีการนี้มีประโยชน์เมื่อคุณต้องการตรวจสอบผลลัพธ์ Cast ก่อนที่จะใช้วัตถุ cast ตัวอย่างเช่น เมื่อคุณต้องการหลีกเลี่ยงข้อยกเว้นและจัดการกรณีความล้มเหลวอย่างนุ่มนวล
- ไวยากรณ์นี้จะพยายามส่ง
เมื่อนําการคัดเลือกไปใช้ ให้พิจารณาแนวทางต่อไปนี้:
- ใช้การจับคู่รูปแบบกับ
is: รวมการตรวจสอบประเภทและส่งในขั้นตอนเดียว - การใช้คําหลัก
isที่มี cast อย่างชัดเจน: แยกประเภทการตรวจสอบและแปลงเป็นสองขั้นตอนเพื่อให้สามารถควบคุมกระบวนการหล่อได้มากขึ้น - การใช้คําสําคัญ
as: พยายามแปลงและจัดการความล้มเหลวอย่างนุ่มนวลโดยส่งคืนค่า null
- ใช้การจับคู่รูปแบบกับ
การทําความเข้าใจเทคนิคการคัดเลือกเหล่านี้เป็นสิ่งสําคัญสําหรับการทํางานกับพอลิมอฟิสและการรับทอดใน C#
หลีกเลี่ยงข้อผิดพลาดทั่วไปเมื่อใช้งาน polymorphism
เมื่อเป้าหมายของคุณคือโพลีมอฟิสต์ที่ยึดตามการสืบทอดนี่คือสิ่งที่ต้องหลีกเลี่ยงและบางสิ่งที่ต้องทําให้แน่ใจว่า:
หลีกเลี่ยงการใช้คลาสและวิธีการที่ปิดผนึก: คลาสและวิธีการที่ปิดผนึกไม่สามารถสืบทอดหรือแทนที่ได้ซึ่ง จํากัด ความสามารถในการใช้พอลิมอฟิสติก ถ้าคุณปิดผนึกคลาสหรือเมธอด คุณจะป้องกันไม่ให้ส่วนขยายและการปรับแต่งเพิ่มเติม เช่น:
public sealed class BankAccount { } // This class can't be inheritedหลีกเลี่ยงการใช้วิธีการแบบคงที่มากเกินไป วิธีการแบบคงที่เป็นสมาชิกของคลาสแทนที่จะเป็นอินสแตนซ์ของคลาส พวกเขาไม่สามารถถูกแทนที่ซึ่งหมายความว่าพวกเขาไม่ได้มีส่วนร่วมในพอลิมอฟิส
public static void PrintMessage() { } // This method can't be overriddenหลีกเลี่ยงการมีเพศสัมพันธ์แน่น การมีเพศสัมพันธ์หนาแน่นเกิดขึ้นเมื่อคลาสหรือส่วนประกอบในระบบขึ้นอยู่กับกันและกันเป็นอย่างมาก ซึ่งหมายความว่าการเปลี่ยนแปลงในคลาสหนึ่งสามารถส่งผลโดยตรงต่อชั้นเรียนอื่น ทําให้ระบบมีความยืดหยุ่นและยากขึ้นในการบํารุงรักษา การมีเพศสัมพันธ์ที่หนาแน่นอาจนําไปสู่ปัญหาในการทดสอบ ขยาย และปรับเปลี่ยนโค้ด
public class BankAccount { public void TransferFunds(SavingsAccount savingsAccount) { // Tight coupling with SavingsAccount } }หลีกเลี่ยงการใช้คําหลัก 'ใหม่' โดยไม่มีเหตุผลที่ดี คําหลัก 'ใหม่' จะซ่อนเมธอดระดับฐานในคลาสที่ได้รับซึ่งอาจทําให้เกิดความสับสนและลักษณะการทํางานที่ไม่คาดคิด ใช้คําสําคัญ 'ใหม่' เมื่อคุณต้องการซ่อนเมธอดคลาสพื้นฐานโดยตั้งใจเท่านั้น
public class Dog : Animal { public new void MakeSound() // Hides the base class method. Better to use 'override' { Console.WriteLine("The dog barks."); } }ตรวจสอบให้แน่ใจว่าลายเซ็นของเมธอดสอดคล้องกัน ตรวจสอบให้แน่ใจว่าวิธีการแทนที่ในคลาสที่ได้รับมามีลายเซ็นเดียวกันกับวิธีการคลาสพื้นฐาน การเปลี่ยนลายเซ็นของเมธอด จะทําให้วิธีการซ่อนแทนที่จะแทนที่
public class Animal { public virtual void MakeSound(string sound) { Console.WriteLine("The animal makes a sound."); } } public class Dog : Animal { // Method signature doesn't match the base class public override void MakeSound() { Console.WriteLine("The dog barks."); } }
สรุป
โพลีมอฟิฟิกที่ใช้การสืบทอดใน C# ช่วยให้คุณสามารถสร้างลําดับชั้นของคลาสที่สืบทอดลักษณะการทํางานและคุณสมบัติจากคลาสพื้นฐานได้ กลไกการสืบทอดนี้จะช่วยให้คุณสามารถจัดการกับออบเจ็กต์ของคลาสที่ได้รับมาเป็นออบเจ็กต์ของคลาสพื้นฐาน ความสามารถในการปฏิบัติต่อออบเจ็กต์คลาสที่ได้รับมาเป็นสมาชิกของคลาสพื้นฐานช่วยให้คุณสามารถเขียนโค้ดที่ทํางานกับออบเจ็กต์หลายชนิดโดยไม่ทราบชนิดเฉพาะในเวลาที่คอมไพล์ โดยการทําความเข้าใจเทคนิคการคัดเลือกเพื่อหลีกเลี่ยงข้อผิดพลาดทั่วไปและทําตามแนวทางปฏิบัติที่ดีที่สุดคุณสามารถใช้โพลิมอฟิกในแอปพลิเคชัน C# ของคุณได้อย่างมีประสิทธิภาพ