Function Procedures II

29 September 2016

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

นี่เป็นเนื้อหาที่คุณจะได้เรียนในบทนี้

  • Function overloading
  • Passing by reference
  • Recursive function
  • Variables and scope

Function overloading

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

Module FunctionOverloadingExample

    Sub Main()

        Tripple("One")
        Tripple(5)

        Multiparameter(1, "Two")
        Multiparameter("Two", 1)
        Multiparameter(True, 3.14)
        Multiparameter(1, 2, 3)

    End Sub

    Sub Tripple(ByVal s As String)
        Console.WriteLine(s + s + s)
    End Sub

    Sub Tripple(ByVal s As Integer)
        Console.WriteLine(s * 3)
    End Sub

    Sub Multiparameter(ByVal a As Integer, ByVal b As String)
        Console.WriteLine("Integer, String")
    End Sub

    Sub Multiparameter(ByVal a As String, ByVal b As Integer)
        Console.WriteLine("String, Integer")
    End Sub

    Sub Multiparameter(ByVal a As Boolean, ByVal b As Double)
        Console.WriteLine("Boolean, Double")
    End Sub

    Sub Multiparameter(ByVal a As Integer, ByVal b As Integer, ByVal c As Integer)
        Console.WriteLine("Integer, Integer, Integer")
    End Sub

End Module

ในตัวอย่าง เป็นการสร้างและใช้งาน overloaded function โดยเราได้สร้างมาสองฟังก์ชันคือ Tripple() เป็นฟังก์ชันสำหรับแสดงผลจำนวนสามเท่าของข้อมูล ซึ่งเราได้ทำการ overload ฟังก์ชันนี้ไป 2 ฟังก์ชัน

 Tripple("One")
 Tripple(5)

นี่เป็นการใช้งาน เราสามารถเรียกใช้โดยการใส่ค่าจากการ overload โดยภาษา Visual Basic จะทำการเลือกใช้ฟังก์ชันที่มีพารามิเตอร์ตรงกันกับอากิวเมนต์ที่เราส่งเข้าไปอัตโนมัติ ถ้าข้อมูลที่ส่งเข้าไปเป็น String โปรแกรมจะแสดง String นั้นต่อกัน 3 ครั้ง และถ้าเป็นตัวเลขโปรแกรมจะแสดงผลจำนวนสามเท่าของตัวเลข

ต่อมาเราสร้างฟังก์ชัน Multiparameter() และเพิ่มจำนวนพารามิเตอร์มากขึ้น ซึ่งฟังก์ชันนี้มีทั้งหมด 4 overload เราสามารถเรียกใช้เช่นเดียวกัน การสลับตำแหน่งหรือเปลี่ยนประเภทข้อมูลถือว่ามันเป็นคนละฟังก์ชัน (overloaded)

OneOneOne
15
Integer, String
String, Integer
Boolean, Double
Integer, Integer, Integer

และนี่เป็นผลลัพธ์จาก function overloading

Warning: ถึงแม้ว่าฟังก์ชันมีการ Return ค่าได้ แต่คุณไม่สามารถใช้การ Return ค่าที่แตกต่างกันสำหรับ function overloading ได้

ในความเป็นจริง overloaded function ในภาษา Visual Basic มีมากมาย เช่นฟังก์ชัน Console.WriteLine() ก็เป็นหนึ่งในตัวอย่างของ overloaded function เพราะว่าเราสามารถส่งตัวแปรประเภทต่างๆ เข้าไปได้

Passing by reference

โดยทั่วไปเมื่อเราเรียกใช้ฟังก์ชันและส่งอากิวเมนต์ไป โปรแกรมจะทำการคัดลอกข้อมูลไปสร้างเป็นตัวแปiใหม่ ซึ่งก็คือพารามิเตอร์ที่เรากำหนดไว้ในฟังก์ชัน แต่อย่างไรก็ตามเราสามารถส่งพารามิเตอร์ด้วยวิธีการ passing by reference ได้ ซึ่งจะทำให้ในฟังก์ชันสามารถใช้ตัวแปรเดียวกันกับตัวแปรต้นฉบับได้

ต่อไปเป็นตัวอย่างการส่งค่าด้วยการ passing by reference ในภาษา Visual Basic

Module ByReferenceParameterExample

    Sub Main()

        ' Passing by value
        Dim a As Integer = 1
        Dim b As Integer = 9
        Console.WriteLine("Before swap a = {0}, b = {1}", a, b)
        Swap(a, b)
        Console.WriteLine("After swap a = {0}, b = {1}", a, b)
        Console.WriteLine()

        ' Passing by reffernece
        Dim c As Integer = 1
        Dim d As Integer = 9
        Console.WriteLine("Before swap c = {0}, d = {1}", c, d)
        SwapRef(c, d)
        Console.WriteLine("After swap c = {0}, d = {1}", c, d)

    End Sub

    Sub Swap(ByVal a As Integer, ByVal b As Integer)
        Dim temp As Integer = a
        a = b
        b = temp
        Console.WriteLine("Swapped")
    End Sub

    Sub SwapRef(ByRef a As Integer, ByRef b As Integer)
        Dim temp As Integer = a
        a = b
        b = temp
        Console.WriteLine("Swapped")
    End Sub

End Module

ในตัวอย่าง เป็นโปรแกรมสลับค่าของตัวเลขระหว่างตัวแปรสองตัว ซึ่งเราสร้างฟังก์ชันมาสองแบบคือ pass by value และ pass by reference สำหรับการสลับค่าของตัวเลข เราจะมาดูว่ามันแตกต่างกันอย่างไร

Sub Swap(ByVal a As Integer, ByVal b As Integer)
    Dim temp As Integer = a
    a = b
    b = temp
    Console.WriteLine("Swapped")
End Sub

ฟังก์ชันแรกของเราคือฟังก์ชัน Swap() ซึ่งเป็นการส่งค่าปกติ คุณจะสังเกตเห็นคำสั่ง ByVal ถูกใช้ในการประกาศพารามิเตอร์ของฟังก์ชัน ดังนั้นเมื่อเราเรียกใช้ฟังก์ชันนี้ โปรแกรมจะสร้างตัวแปรใหม่สำหรับใช้ภายในฟังก์ชัน

Sub SwapRef(ByRef a As Integer, ByRef b As Integer)
    Dim temp As Integer = a
    a = b
    b = temp
    Console.WriteLine("Swapped")
End Sub

ต่อมาเป็นฟังก์ชัน SwapRef() นี่เป็นการส่งพารามิเตอร์ด้วยการอ้างอิงจากตัวแปรเดียวกัน ที่เราได้ใส่เป็นอากิวเมนต์ เราเรียกว่า passing by reference ผลลัพธ์ก็คือเมื่อเราทำการเปลี่ยนแปลงค่าของตัวแปรภายในฟังก์ชันนี้ ตัวแปรนอกฟังก์ชันก็จะเปลี่ยนแปลด้วยเช่นกัน

Before swap a = 1, b = 9
Swapped
After swap a = 1, b = 9

Before swap c = 1, d = 9
Swapped
After swap c = 9, d = 1

และนี่เป็นผลลัพธ์ของโปรแกรมสลับตัวเลข คุณจะเห็นว่าค่าของตัวแปร c และ d ในฟังก์ชัน Main() เปลี่ยนแปลงไปด้วยหลังจากการเรียกใช้ฟังก์ชัน SwapRef() ที่มีการส่งค่าแบบ passing by reference

การส่งค่าพารามิเตอร์แบบ passing by reference มีประโยนช์มากในการเขียนโปรแกรมที่ต้องการประสิทธิภาพและความเร็ว ในกรณีที่มีการส่งข้อมูลเป็นจำนวนมากเข้าไปทำงานในฟังก์ชัน ยกตัวอย่างเช่น การส่งอาเรย์ที่มีขนาดใหญ่ไปในฟังก์ชัน

Recursive function

Recursive function คือฟังก์ที่ชันเรียกใช้ตัวของมันเอง หลักการทำงานของฟังก์ชันแบบ recursive คือโปรแกรมจะเรียกใช้ฟังก์ชันเดิมซ้ำๆ เพื่อทำผลลัพธ์ที่ได้จากการทำงานก่อนหน้ามาใช้ในการคำนวณการทำงานในปัจจุบัน โดยสิ่งที่สำคัญที่สุดของ recursive function คือมันจะต้องมีเงือนไขสำหรับหยุดการเรียกซ้ำ เราเรียกว่า base condition

ตัวอย่างของการใช้งาน recursive function เช่น การหาค่า factorial ของตัวเลข ซึ่งผลลัพธ์ของ n! จะเท่ากับ ผลคูณจาก 1 ถึง n หรือ n * (n - 1)! ดังนั้นในการที่จะทราบค่าของ n! เราจำเป็นต้องการค่า factorial ของตัวเลขก่อนหน้ามันก่อน จนถึง 0! ซึ่งมีค่าเท่ากับ 1 มาดูตัวอย่างการใช้งาน recursive function เรียกตัวมันเองในการหาค่า factorial ของตัวเลข

Module RecursiveFunction

    Sub Main()

        Console.WriteLine("3! = {0}", Factorial(3))
        Console.WriteLine("5! = {0}", Factorial(5))
        Console.WriteLine("10! = {0}", Factorial(10))

    End Sub

    Function Factorial(ByVal number As Integer) As Integer
        If number = 0 Then
            Return 1
        Else
            Return number * Factorial(number - 1)
        End If
    End Function

End Module

ในตัวอย่างเราได้สร้างฟังก์ชัน Factorial() สำหรับหาค่า factorial และมันเป็น recursive function เพราะว่ามันมีการเรียกใช้ตัวเอง และมีการกำหนด base condition สำหรับการหยุดการทำงานของ recursive ต่อไปเราจะอธิบายทีละบรรทัดในฟังก์ชันดังกล่าว

Return number * Factorial(number - 1)

คำสั่งนี้เป็นการทำ recursive call หรือการเรียกใช้ตัวเอง เพราะว่าสูตรในการหาค่า factorial คือ n * (n - 1)! ดังนั้นในคำสั่ง number * Factorial(number - 1) เป็นส่วนที่ทำให้เกิด recursive ขึ้น ยกตัวอย่างเช่น เราต้องการหาค่า factorial ของ 3 โปรแกรมจะไปหาค่า factorial ของ 2 มาก่อน และในการที่จะได้ค่า factorial ของ 2 ก็ต้องได้ค่าของ 1 ก่อนเช่นกัน และเพราะว่า 1! และ 0! เท่ากับหนึ่ง ดังนั้นในคำสั่งต่อไป

If number = 0 Then
    Return 1
    ...

นี่เป็นคำสั่งใรการสร้าง base condition เมื่อตัวเลขเป็น 0 เราจะส่งค่า 1 กับไป และโปรแกรมจะนำไปคูณย้อนกับขึ้นไปเรื่อยๆ จนกระทั่งมันได้ค่าของ 3! ซึ่งเป็นคำตอบ

3! = 6
5! = 120
10! = 3628800

นี่เป็นผลลัพธ์การทำงานของโปรแกรม ในการหาค่าของ factorial นั้น ตัวเลขจะเพิ่มขึ้น n เท่าจากตัวเลขก่อนหน้า ดังนั้นการใช้ข้อมูลแบบ Integer ที่มีค่าสูงสุดเป็น 2,147,483,647 จะเก็บค่าได้สูงสุดคือผลลัพธ์ของ 12! เท่านั้น

นี่เป็นเพียงตัวอย่างที่ง่ายที่สุดสำหรับ recursive function มันยังถูกนำไปใช้สำหรับอัลกอริทึมต่างๆ เพื่อเพิ่มประสิทธิภาพและความเร็วในการทำงาน เช่น binary search merg sorting การท่องไปในต้นไม้หรือกราฟ หรืออัลกอริทึมประเภท divide and conquer ทั้งหลาย

Variables and scope

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

Module VariableScope

    ' This variable can be used 
    ' every where In this Module
    Dim a As Integer = 0

    Sub Main()

        ' This function can use in this procedure and it sub block
        Dim b As Integer = 1

        If b = 1 Then
            ' This variable can use in this IF block only
            Dim d As Integer = 2
        End If

    End Sub

    Sub MyProcudure()
        ' This variable can use in this procedure only
        Dim d As Integer = 1
    End Sub

End Module

ในตัวอย่าง เป็นตัวอย่างแสดงขอบเขตของโปรแกรมในภาษา Visual Basic ซึ่งสามารถใช้ได้ในบริบทที่แตกต่างกัน

Dim a As Integer = 0

เราประกาศตัวแปร a ภายในโมดูล ซึ่งจะทำให้มันสามารถเข้าถึงได้จากทุกที่ที่อยู่ในโมดูลนี้ หรือเราเรียกมันว่า global variable สำหรับโมดูลนั่นเอง

Dim d As Integer = 1

ต่อมาตัวแปร d ที่อยู่ในโพซีเยอร์ MyProcudure() ตัวแปรนี้ก็สามารถใช้ได้เฉาะภายในนี้ และไม่สามารถเข้าถึงได้จากฟังก์ชันอื่น ถ้าคุณต้องการเข้าถึงค่าจากตัวแปรของฟังก์ชันอื่น คุณต้องใช้วิธี pass by reffernce ตัวแปรนั้นเข้ามาในฟังก์ชันนี้ ที่คุณเพิ่งได้เรียนรู้ไปก่อนหน้านี้

Dim b As Integer = 1

ต่อไปในฟังก์ชัน Main() เราได้ประกาศตัวแปร b ซึ่งสามารถใช้ได้สำหรับในฟังก์ชันนี้ และบล็อคย่อยของมัน เช่น บล็อคของ If For While หรือ Do While เป็นต้น เช่นเดียวกันกับโมดูลที่มีฟังก์ชันเป็นบล็อคย่อย

Dim d As Integer = 2

เช่นกัน ตัวแปร d จึงสามารถใช้ได้ในบล็อคคำสั่ง If และบล็อคย่อยของมันเท่านั้น

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

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