Inheritance

11 February 2016

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

Inheritance คืออะไร

Inheritance (การสืบทอด) เป็นคุณสมบัติหนึ่งในการเขียนโปรแกรมที่ใช้กับการสร้างคลาส โดยการถ่ายทอดสมาชิกจากคลาสหนึ่งไปยังอีกคลาสหนึ่ง โดยสมาชิกที่ว่านี้ก็คือสมาชิกของคลาสนั้นเอง ซึ่งมีตัวแปรและเมธอด ในภาษา C# เราเรียกคลาสหลักที่สืบทอดไปยังคลาสอื่นว่า Base class และคลาสที่ถูกสืบทอดนั้นจะเรียกว่า Delivered class

ตัวอย่างของการสืบทอดคลาสกับการใช้งานจริง เช่น เรามีคลาสของสัตว์ซึ่งเป็น Base class คลาสนี้มีคุณสมบัติและการทำงานบางอย่างที่สัตว์ทุกชนิดสามารถทำได้ หลังจากนั้นเราอาจจะมีการสร้างคลาสใหม่ที่มีการสืบทอดจากคลาสนี้ ซึ่งเป็นสัตว์แต่ละชนิด เป็นต้น

ในการสืบทอดในภาษา C# นั้นจะใช้เครื่องหมายโคลอน (colon) : โดยมีรูปแบบการสร้างคลาสเพื่อสืบทอดดังนี้

class DeliveredClass: BaseClass {
    // statemets
}

จากรูปแบบด้านบนนั้นเป็นวิธีของการเขียนโปรแกรม โดยมีความหมายว่า BaseClass สืบทอดคุณสมบัติทั้งหมดไปยัง DeliveredClass ในตอนนี้ DeliveredClass มีคุณสมบัติเท่ากับ BaseClass และนอกจากนี้มันยังสามารถเพิ่มสมาชิกไม่ว่าจะเป็นตัวแปรหรือเมธอดได้ ดังนั้น Delivered class จะมีคุณสมบัติหรือประสิทธิภาพเท่ากับหรือมากกว่า Base class เสมอ

ในการสืบทอดนั้นสมาชิกที่มีการกำหนดการเข้าถึงเป็น private จะถูกสืบทอดไปยังคลาสย่อย และนอกจากนี้ Constructor และ Destructor ยังไม่สามารถสืบทอดด้วยเช่นกัน ต่อไปมาดูตัวอย่างของการ Inheritance ในภาษา C#

สร้าง Inheritance คลาส

ต่อไปมาดูตัวอย่างของการใช้งานคุณสมบัติการสืบทอด เพื่อสืบทอดคุณสมบัติของคลาสในภาษา C# เราจะทการสร้างคลาสของรูปสี่เหลี่ยมมูมฉาก (Rectangle) หลังจากนั้นเราจะสร้างคลาสที่สืบทอดคุณสมบัติจากคลาสนี้คือคลาสของรูปสี่เหลี่ยมมุมฉากในสามมิติ (Cuboid)

using System;

class InheritanceExample
{
    static void Main(string[] args)
    {
        Rectangle rec1 = new Rectangle(3, 4);
        Console.WriteLine("Rectangle 1");
        Console.WriteLine("size [{0}, {1}]", rec1.x, rec1.y);
        Console.WriteLine("Area = {0}", rec1.GetArea());
        Console.WriteLine();

        Cuboid cub1 = new Cuboid(5, 3, 4);
        Console.WriteLine("Cuboid 1");
        Console.WriteLine("size [{0}, {1}, {2}]", 
            cub1.x, cub1.y, cub1.z);
        Console.WriteLine("Volume = {0}", cub1.GetVolume());
        Console.WriteLine();

        Cuboid cub2 = new Cuboid(10, 10, 10);
        Console.WriteLine("Cuboid 2");
        Console.WriteLine("size [{0}, {1}, {2}]", 
            cub2.x, cub2.y, cub2.z);
        Console.WriteLine("Volume = {0}", cub2.GetVolume());
    }
}

class Rectangle
{
    public int x;
    public int y;

    public Rectangle(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public double GetArea()
    {
        return x * y;
    }
}

class Cuboid : Rectangle
{
    public int z;

    public Cuboid(int x, int y, int z) : base(x, y)
    {
        this.z = z;
    }

    public double GetVolume()
    {
        return GetArea() * z;
    }
}

ในตัวอย่าง เราได้สร้างคลาส Rectangle ซึ่งเป็นคลาสของรูปสี่เหลี่ยมมุมฉาก ที่ประกอบไปด้วยความยาวในแนวแกน x และ y และมีเมธอด GetArea() สำหรับหาพื้นที่ของรูปสี่เหลี่ยม ซึ่งคลาสนี้เป็นคลาสของรูปสี่เหลี่ยมในสองมิติ

class Cuboid : Rectangle
{
    public int z;

    public Cuboid(int x, int y, int z) : base(x, y)
    {
        this.z = z;
    }

    public double GetVolume()
    {
        return GetArea() * z;
    }
}

ต่อมาเราได้สร้างคลาส Cuboid ซึ่งเป็นคลาสของสี่เหลี่ยมในสามมิติ และคล่าได้สืบทอดมาจากคลาส Rectangle ดังนั้นคลาส Cuboid จะได้รับคุณสมบัติทั้งหมดที่มีใน Base class ที่ประกอบไปด้วยตัวแปรและเมธอด และเราได้สร้างตัวแปร z สำหรับเก็บความยาวในแกน z และสร้างเมธอด GetVolume() สำหรับหาปริมาตรของรูปทรงสี่เหลี่ยมนี้

และในการสืบทอดนั้น Constructor จะไม่สืบทอดมาด้วย ดังนั้นใน Constructor ของคลาส Cuboid เราได้เรียกใช้ Constructor ของ base class ด้วยคำสั่ง : base(x, y) ตามหลัง Constructor ของมันเอง

Rectangle 1
size [3, 4]
Area = 12

Cuboid 1
size [5, 3, 4]
Volume = 60

Cuboid 2
size [10, 10, 10]
Volume = 1000

นี่เป็นผลลัพธ์การทำงานของโปรแกรม เราได้นำคลาสทั้งสองมาสร้างออบเจ็คของรูปสี่เหลี่ยมและรูปทรงสี่เหลี่ยม เราได้ลดการเขียนโปรแกรม โดยการใช้งานคุณสมบัติบางส่วนจากคลาส Rectangle โดยการที่ไม่ต้องประกาศตัวแปร x y และเมธอด GetArea() ใหม่จากการ Inheritance ของคลาสหรือมันเป็นการ reuse code

Note: คุณสมบัติที่เป็นแบบ private จะไม่สามารถถ่ายทอดได้ เราจำเป็นต้องเปลี่ยนตัวแปร width และ height เป็น protected ก่อน

Overriding Base Class

ในการสืบทอดนั้น ยังมีความสามารถที่เราสามารถทำการ Override ซึ่งคือการที่ Delivered Class สามารถที่จะกำหนดการทำงานให้กับเมธอดใหม่เพื่อให้สอดคล้องกับการทำงานในคลาส ต่อไปเป็นตัวอย่างของการ Override คลาสในภาษา C#

using System;

class OverrideExample
{
    static void Main(string[] args)
    {
        AddNumber x = new AddNumber();
        x.a = 2;
        x.b = 3;
        Console.WriteLine("{0} + {1} = {2}", x.a , x.b, x.Result());

        MultiplyNumber y = new MultiplyNumber();
        y.a = 4;
        y.b = 5;
        Console.WriteLine("{0} * {1} = {2}", y.a, y.b, y.Result());
    }
}

class AddNumber
{
    public int a;
    public int b;

    public virtual int Result()
    {
        return a + b;
    }
}

class MultiplyNumber : AddNumber
{
    public override int Result()
    {
        return a * b;
    }
}

ในตัวอย่าง เรามีคลาส AddNumber ซึ่งเป็นคลาสสำหรับบวกตัวเลขสองตัว และคลาสนี้มีเมธอดสำหรับหาผลลัพธ์ของการบวกตัวเลขคือเมธอด Result() และเราได้ใช้คำสั่ง virtual ในการประกาศเมธอดเพื่อกำหนดให้เมธอดนี้สามารถที่จะ Override ได้โดย Delivered Class ของมัน

class MultiplyNumber : AddNumber
{
    public override int Result()
    {
        return a * b;
    }
}

เราสร้างคลาส MultiplyNumber และได้สืบทอดจากคลาส AddNumber คลาสนี้เป็นคลาสสำหรับหาผลคูณของตัวเลขสองตัว และในเมธอด Result() เราต้องทำการเปลี่ยนแปลงสมการสำหรับการคูณ และเราต้องการใช้ชื่อเมธอดเดิมกับคลาสหลัก เราจะใช้คำสั่ง override ในการประกาศเมธอด

2 + 3 = 5
4 * 5 = 20

นี่เป็นผลลัพธ์การทำงานของโปรแกรม คุณจะเห็นว่าเราได้ทำการ override เมธอด Result() ใหม่สำหรับในคลาสของการคูณตัวเลข ดังนั้นสิ่งที่สำคัญของการ override คือเราสามารถใช้เมธอดชื่อเดียวกันแต่ผลลัพธ์การทำงานต่างกันตามวัตถุประสงค์ของคลาส

ในบทนี้คุณได้เรียนรู้เกี่ยกวับคุณสมบัติ Inheritance ในการเขียนโปรแกรมเชิงวัตถุที่มีในภาษา C# และการ Override และการใช้คำสั่ง base ในการเข้าถึง Base class ของมัน

บทความนี้เป็นประโยชน์หรือไม่? Yes · No