Inheritance

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

Inheritance คืออะไร

ในการเขียนโปรแกรมเชิงวัตถุ inheritance (การสืบทอด) คือการที่คลาสนั้นสร้างมาจากคลาสอื่น ในภาษา Visual Basic นั้น เราสามารถใช้คุณสมบัตินี้ในการสร้างคลาสใหม่ (delivered class) ซึ่งสามารถสืบทอดคุณสมบัติ เมธอด หรืออีเวนต์ ของคลาสหลักได้ (base class) นอกจากนี้ ในคลาสใหม่ยังสามารถกำหนดสมาชิกของมันได้เพิ่มเติม หรือกล่าวอีกนัยหนึ่ง การสืบทอดคือการที่คลาสสร้างมาจากคลาสอื่นและต่อเติมความสามารถเพิ่มสำหรับตัวมันเอง

ในการสร้างคลาสที่สืบทอดจะใช้คำสั่ง Inherits ตามด้วยชื่อของ base class ในบรรทัดแรกภายในบล็อคของ delivered class มาดูตัวอย่างการสืบทอดคลาสในภาษา Visual Basic

Class Rectangle

Public width As Integer
Public height As Integer

Function Area() As Integer
Return width * height
End Function

End Class

Class Hyperrectangle
Inherits Rectangle

Public depth As Integer

Function Volume() As Integer
Return width * height * depth
End Function

End Class

นี่เป็นตัวอย่างการสืบทอดของคลาสในภาษา Visual Basic เราได้สร้าง base class คือคลาส Rectangle ซึ่งเป็นคลาสของรูปสี่เหลี่ยมในสองมิติ ในคลาสนี้มีสมาชิกที่เป็นตัวแปรสำหรับเก็บความยาวของรูปสี่เหลี่ยม และเมธอดสำหรับหาพื้นที่

ต่อมาเราสร้างคลาส Hyperrectangle ซึ่งทำการสืบทอกจากคลาส Rectangle เราเรียกคลาสที่สร้างมานี้ว่า delivered class โดยมันจะมีตัวแปรและเมธอดเหมือนกับ base คลาสทุกอย่าง ในคลาสใหม่นี้เรายังประกาศตัวแปรและสร้างเมธอดเพิ่มเติม ต่อไปมาดูตัวอย่างการสร้างออบเจ็คและใช้งาน

Class Rectangle

Public width As Integer
Public height As Integer

Function Area() As Integer
Return width * height
End Function

End Class

Class Hyperrectangle
Inherits Rectangle

Public depth As Integer

Function Volume() As Integer
Return width * height * depth
End Function

End Class

Module InheritanceExample

Sub Main()

Dim box As Hyperrectangle = New Hyperrectangle()
box.width = 3
box.height = 4
box.depth = 5

Console.WriteLine("Box1 area = {0}", box.Area())
Console.WriteLine("Box1 volume = {0}", box.Volume())

End Sub

End Module

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

Box area = 12
Box volume = 60

นี่เป็นผลลัพธ์ของโปรแกรมในตัวอย่างการสืบทอดคลาสในภาษา Visual Basic

Info: การสืบทอดในภาษา Visual Basic ตัวแปร property เมธอด และอีเว้นต์ จะถูกสืบทอดไปยังคลาสใหม่ทั้งหมด ยกเว้นตัวแปรที่มีระดับการเข้าถึงเป็น Private และคอนสตรัคเตอร์ของคลาสที่จะไม่ถูกสืบทอด

Overriding method

ในการสืบทอดคลาสในภาษา Visual Basic นั้นเมธอดของ base class จะถูกสืบทอดมาด้วย และมันยังคงรักษาการทำงานจากคลาสเดิมอยู่ เราสามารถทำการ override เมธอดโดยที่เมธอดยังมีชื่อเหมือนเดิมกับ base class แต่การทำงานจะเปลี่ยนไปใน delivered class มาดูตัวอย่างการ override เมธอด

Class AnnualSalary

Overridable Function PayEmployee(
ByVal salary As Double) As Decimal
PayEmployee = salary * 12
End Function

End Class

Class BonusAnnualSalary
Inherits AnnualSalary

Public bonusRate = 1.8

Overrides Function PayEmployee(
ByVal salary As Double) As Decimal
PayEmployee = MyBase.PayEmployee(salary) * bonusRate
End Function

End Class

Module OverrideMethod

Sub Main()

Dim annualSal As New AnnualSalary()
Dim annualSalWithBonus As New BonusAnnualSalary()

Dim salary As Double = 6628

Console.WriteLine("Your salary $" & salary)
Console.WriteLine("Your annual salary is $" &
annualSal.PayEmployee(salary))
Console.WriteLine("Your annual salary with bonus is $" &
annualSalWithBonus.PayEmployee(salary))

End Sub

End Module

ในตัวอย่างเป็นโปรแกรมในการคำนวณหารายได้ประจำปี โดยคำนวณจากเงินเดือน เราได้สร้างคลาสมาสองคลาสสำหรับตัวอย่างการ override method นี้

Class AnnualSalary

Overridable Function PayEmployee(
ByVal salary As Double) As Decimal
PayEmployee = salary * 12
End Function

End Class

นี่เป็นคลาสหลักของเรา และมันมีเมธอด PayEmployee() สำหรับคำนวณรายได้ต่อปี เราใช้คำสั่ง Overridable เพื่อกำหนดให้เมธอดนี้สามาร override ได้ใน delivered class ที่คุณเห็นในโปรแกรม การใช้คำสั่ง PayEmployee = salary * 12 นั้นให้ผลลัพธ์เหมือนกันกับคำสั่ง Return

Class BonusAnnualSalary
Inherits AnnualSalary

Public bonusRate = 1.8

Overrides Function PayEmployee(
ByVal salary As Double) As Decimal
PayEmployee = MyBase.PayEmployee(salary) * bonusRate
End Function

End Class

ต่อมาเราได้สร้างคลาส BonusAnnualSalary ซึ่งสืบทอดจากจากคลาส AnnualSalary เราได้ทำการ override method PayEmployee() จาก base class โดยข้างหน้าเมธอดเราใช้คำสั่ง Overrides และภายในเมธอดนี้ เรายังสามารถเข้าถึงเมธอดของ base class ได้ด้วยคำสั่ง MyBase.PayEmployee(salary)

Your salary $6628
Your annual salary is $79536
Your annual salary with bonus is $143164.8

นี่เป็นผลลัพธ์ของโปรแกรมที่มีอัตราของโบนัสอยู่ 1.8 จากการมีเงินเดือน $6628 จะมีรายได้ต่อปีพร้อมโบนัสเป็น $143164.8

การใช้คำสั่ง Me และ MyBase

การสืบทอดคลาสนั้นทำให้เราสามารถนำโค้ดเดิมกลับมาใช้ได้โดยไม่ต้องเขียนใหม่ทั้งหมด หลังจากที่การสืบทอดสำเร็จ delivered class จะมีตัวแปรและเมธอดเหมือนกันกับ base class ทุกอย่าง ทำให้การใช้งานภายในคลาสนั้นอ้างถึงสมาชิกของตัวเอง ดังนั้นคุณจำเป็นต้องทราบในการใช้งานของคำสั่ง Me และ MyBase

  • คำสั่ง Me: เป็นคำสั่งในการอ้างถึงสมาชิกของออบเจ็คหรือคลาสปัจจุบัน โดยปกติการเข้าถึงสมาชิกภายในคลาสปัจจุบันนั้นใช้คำสั่งนี้โดยปริยาย
  • คำสั่ง MyBase: เป็นคำสั่งในการอ้างถึงสมาชิกของออบเจ็คหรือคลาสของ base class โดยการเรียกใช้นั้นอยู่ใน delivered class

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

Class Point2D

Public x As Double
Public y As Double

Sub New(ByVal x As Double, ByVal y As Double)
Me.x = x
Me.y = y
End Sub

Function Distance(ByVal point As Point2D) As Double
Return Math.Sqrt(Math.Pow(point.x - x, 2) + Math.Pow(point.y - y, 2))
End Function

End Class

Class Point3D
Inherits Point2D

Public z As Double

Sub New(ByVal x As Double, ByVal y As Double, ByVal z As Double)
MyBase.New(x, y)
Me.z = z
End Sub

Function Distance2D(ByVal point As Point3D) As Double
Return MyBase.Distance(point)
End Function

Function Distance3D(ByVal point As Point3D) As Double
Return Math.Sqrt(Math.Pow(point.x - x, 2) +
Math.Pow(point.y - y, 2) +
Math.Pow(point.z - z, 2))
End Function

End Class

Module InheritanceMeMyBase

Sub Main()

Dim point1 As New Point2D(-5, -4)
Dim point2 As New Point2D(8, 3.5)
Console.WriteLine("Distance between (-5, -4) and (8, 3.5) = " &
point1.Distance(point2))

Dim point3 As New Point3D(1, 2, 5)
Dim point4 As New Point3D(-1, 0, -8)
Console.WriteLine("Distance between (1, 2, 5) and (-1, 0, -8) = " &
point3.Distance3D(point4))

Console.WriteLine("Distance between (1, 2, 5) and (-1, 0, -8) in 2D = " &
point3.Distance2D(point4))
Console.WriteLine("Distance between (1, 2, 5) and (-1, 0, -8) in 2D = " &
point3.Distance(point4))

End Sub

End Module

ในตัวอย่าง เป็นโปรแกรมในการหาระห่างระหว่างจุดสองจุดในสองมิติและสามมิติ เรามีสองคลาสคือ Point2D เป็นคลาสสำหรับจุดในสองมิติ และ Point3D เป็นคลาสสำหรับจุดในสามมิติ ซึ่งคลาสนี้ได้สืบทอดมาจากคลาส Point2D

Class Point2D

Public x As Double
Public y As Double

Sub New(ByVal x As Double, ByVal y As Double)
Me.x = x
Me.y = y
End Sub

Function Distance(ByVal point As Point2D) As Double
Return Math.Sqrt(Math.Pow(point.x - x, 2) + Math.Pow(point.y - y, 2))
End Function

End Class

นี่เป็นคลาสสำหรับจุดในสองมิติ ในคลาสมีตัวแปร x และ y สำหรับเก็บพิกัดของจุด ในคอนสรัตเตอร์ของคลาสเราได้ประกาศพารามิเตอร์ที่มีชื่อเหมือนกันกับตัวแปรของคลาส ดังนั้นในการเข้าถึงตัวแปรของคลาส เราจะใช้คำสั่ง Me ตามด้วยจุดและชื่อของตัวแปรที่จะเข้าถึง ส่วนฟังก์ชัน Distance() เป็นฟังก์ชันในการหาระยะห่างตามสูตรของพิกัดในสองมิติ ซึ่งนี่เป็นสิ่งที่เกี่ยวกับ variables scope ที่เราได้พูดถึงในส่วนสุดท้ายของบท Function Procedures II

Class Point3D
Inherits Point2D

Public z As Double

Sub New(ByVal x As Double, ByVal y As Double, ByVal z As Double)
MyBase.New(x, y)
Me.z = z
End Sub

Function Distance2D(ByVal point As Point3D) As Double
Return MyBase.Distance(point)
End Function

Function Distance3D(ByVal point As Point3D) As Double
Return Math.Sqrt(Math.Pow(point.x - x, 2) +
Math.Pow(point.y - y, 2) +
Math.Pow(point.z - z, 2))
End Function

End Class

นี่เป็นคลาสสำหรับจุดในสามมิติ คลาสนี้ได้สืบทอดจากคลาส Point2D ในคอนสตรัคเตอร์เป็นการกำหนดค่าเริ่มต้นให้กับออบเจ็ค ในคำสั่ง MyBase.New(x, y) เป็นการเรียกใช้คอนสตรัคเตอร์ของ base class นั้นจะใช้คำสั่ง MyBase สำหรับการอ้างถึง

สำหรับคลาสนี้จะมีเมธอด Distance3D() สำหรับหาระยะห่างของจุดในสามมิติ นอกจากนี้เรายังสร้างฟังก์ชัน Distance2D() และเพราะว่ามันมีความหมายเหมือนกับฟังก์ชัน Distance() เราใช้คำสั่ง MyBase เพื่อเรียกเมธอดจาก base class ในความตั้งในของส่วนนี้เพื่อให้คุณรู้ว่าเราสามารถเข้าถึงสมาชิกของ base class ได้ทั้งหมด

Distance between (-5, -4) and (8, 3.5) = 15.0083310198036
Distance between (1, 2, 5) and (-1, 0, -8) = 13.3041346956501
Distance between (1, 2, 5) and (-1, 0, -8) in 2D = 2.82842712474619
Distance between (1, 2, 5) and (-1, 0, -8) in 2D = 2.82842712474619

นี่เป็นผลลัพธ์ของโปรแกรม ในสองบรรทัดสุดท้ายนั้นการเรียกเมธอด Distance2D() และ Distance() ในออบเจ็คของคลาส Point3D เป็นการทำงานเดียวกันซึ่งเป็นผลจากคำสั่ง MyBase

ในบทนี้ คุณได้เรียนรู้เกี่ยวกับการสืบทอดในภาษา Visual Basic การ Override method รวมถึงการใช้คำสั่ง Me และ MyBase เพื่อจัดการและเข้าถึงสมาชิกภายในคลาสและคลาสหลักของมัน


บทความเกี่ยวกับ Inheritance