800 likes | 979 Views
เมธอด และขอบเขตของตัวแปร. 01204111 คอมพิวเตอร์และการโปรแกรม. เนื้อหา. แนะนำเมธอด การประกาศและใช้งานเมธอด ขอบเขตของตัวแปร. แนะนำเมธอด. การแบ่งงานเป็นส่วน ๆ. ใน Python เราสามารถแบ่งโปรแกรมที่เขียนเป็นฟังก์ชันย่อย ๆ เพื่อลดทั้งความซ้ำซ้อนและความซับซ้อน
E N D
เมธอด และขอบเขตของตัวแปร 01204111 คอมพิวเตอร์และการโปรแกรม
เนื้อหา • แนะนำเมธอด • การประกาศและใช้งานเมธอด • ขอบเขตของตัวแปร
การแบ่งงานเป็นส่วน ๆ • ใน Python เราสามารถแบ่งโปรแกรมที่เขียนเป็นฟังก์ชันย่อย ๆ เพื่อลดทั้งความซ้ำซ้อนและความซับซ้อน • ใน C# เราก็ทำได้เช่นเดียวกัน โดยใช้เมธอด
ฟังก์ชัน vs เมธอด • เมธอดกับฟังก์ชันเป็นชื่อที่ใช้เรียกส่วนของโปรแกรมที่เขียนเป็นส่วนย่อย ๆ เช่นเดียวกัน • อย่างไรก็ตาม เมธอด (method) นั้นมีความหมายที่เฉพาะเจาะจงกว่าในภาษาโปรแกรมเชิงวัตถุ • อย่างไรก็ตาม ก่อนที่เราจะได้ศึกษาการโปรแกรมเชิงวัตถุ เราจะใช้เมธอดในลักษณะเดียวกับฟังก์ชันในภาษา Python
แนวคิด • เราจะเริ่มโดยการยกตัวอย่างการใช้เมธอดในการออกแบบโปรแกรม • ในส่วนนี้จะคล้ายกับเนื้อหาที่เคยพิจารณามาแล้วในส่วนของภาษาไพธอน แต่งานที่ทำจะซับซ้อนขึ้น • ในตอนแรกนี้ นิสิตอาจจะยังไม่เข้าใจไวยากรณ์ในการนิยามเมธอด แต่ขอให้พยายามทำความเข้าใจกับภาพรวมและการนำไปใช้ก่อน
ตัวอย่าง จงเขียนโปรแกรมที่รับจำนวนเต็ม N จากผู้ใช้ แล้วพิมพ์รูปสี่เหลี่ยมขนาด N คอลัมน์ คูณ N บรรทัด ที่ประกอบด้วยตัวอักขระ * Enter N: 3 ****** *** Enter N: 4 ******** **** **** Enter N: 6 ************ ****** ****** ****** ******
วางแผน: ขั้นตอนคร่าว ๆ • รับค่า N • พิมพ์ทีละบรรทัด จำนวน N ครั้ง • แต่ละบรรทัด พิมพ์ * จำนวน N ครั้งแล้วขึ้นบรรทัดใหม่ ************ ****** ****** ****** ******
วางแผน: ภาพรวมของงานที่ต้องทำ โปรแกรมพิมพ์สี่เหลี่ยม รับค่า N พิมพ์สี่เหลี่ยม ขนาด N x N พิมพ์ดาวเป็นแถว ความยาว N ตัวอักษร
เริ่มต้นเขียน: โปรแกรมหลัก โปรแกรมพิมพ์สี่เหลี่ยม • สำหรับงานย่อย ๆ แต่ละงาน เราจะสมมติว่าเรามีคำสั่งสำหรับงานนั้นอยู่แล้ว (แต่จริง ๆ ยังไม่มี) รับค่า N พิมพ์สี่เหลี่ยม ขนาด N x N static void Main() { int n = int.Parse(Console.ReadLine()); PrintSquare(n); Console.ReadLine(); } คำสั่งนี้ยังไม่มีจริงเราต้องเขียนขึ้นมาเอง
เมธอดแสดงสี่เหลี่ยม • เมธอดดังกล่าวจะเรียกใช้เมธอด PrintLineที่ยังไม่มีอยู่จริงเช่นกัน static void PrintSquare(int n) { int i = 0; while(i < n) { PrintLine(n); i++; } } พิมพ์สี่เหลี่ยม ขนาด N x N พิมพ์ดาวเป็นแถว ความยาว N ตัวอักษร คำสั่งนี้ยังไม่มีจริงเราต้องเขียนขึ้นมาเองเช่นกัน
เมธอด PrintLine • สุดท้ายเราจะเขียนเมธอด PrintLine ที่พิมพ์เส้นความยาว n ด้วยดวงดาว static void PrintLine(int n) { int i = 0; while(i < n) { Console.Write("*"); i++; } Console.WriteLine(); }
โปรแกรมทั้งหมด using System;namespace box1{ class Program { static void PrintLine(int n) {int i = 0;while(i < n) {Console.Write("*"); i++; }Console.WriteLine(); } static void PrintSquare(int n) {int i = 0;while(i < n) {PrintLine(n); i++; } } public static void Main(string[] args) {int n = int.Parse(Console.ReadLine());PrintSquare(n);Console.ReadLine(); } }} • โปรแกรมทั้งหมดดูยาวพอสมควร แต่ถ้าเราพิจารณาและทำความเข้าใจกับโปรแกรมเป็นส่วนย่อยไปก่อน เราจะสามารถปะติดปะต่อการทำงานทั้งหมดได้โดยไม่ยากนัก เมธอด PrintLine เมธอด Main เมธอด PrintSquare
การประกาศและใช้งานเมธอดการประกาศและใช้งานเมธอด
รูปแบบการประกาศเมธอด • ไวยากรณ์ในการประกาศเมธอดเป็นดังนี้ static แบบชนิดข้อมูลที่คืนค่าชื่อเมธอด( รายการพารามิเตอร์) { // โปรแกรมของเมธอด } • จากตัวอย่างที่ผ่านมา เราสามารถเขียนเมธอดที่คำนวณแล้วส่งค่ากลับมายังโปรแกรมส่วนที่เรียกใช้ได้ เราต้องระบุแบบชนิดของข้อมูลที่จะคืนค่ากลับนี้เมื่อประกาศเมธอดด้วย • เราจะส่งข้อมูลให้กับเมธอดผ่านทางพารามิเตอร์
คำหลัก static • ในส่วนนี้เราจะเห็นคำว่า staticเมื่อตอนที่เราประกาศเมธอด รวมถึงในตอนหลังที่ใช้ในการประกาศตัวแปรครอบคลุม • เราจะเข้าใจความหมายของคำหลักดังกล่าวมากขึ้นเมื่อได้ศึกษาการโปรแกรมเชิงวัตถุแล้ว ในขั้นนี้ให้ใช้ตามที่ระบุไปก่อน
ตัวอย่างการประกาศ • เมธอดที่คำนวณค่าของพหุนามกำลังสอง ax2 + bx + c static double Poly(double a, double b, double c, double x) { return a*x*x + b*x + c; } รับพารามิเตอร์ a, b, c และ x คืนค่าเป็น double เมธอดชื่อ poly
ตำแหน่งที่ประกาศ using System;namespace met_examples{ class Program { static doublePoly(double a, double b, double c,double x) { return a*x*x + b*x + c; }public static void Main() { } }} • ประกาศเมธอดภายในคลาส • ภายนอกเมธอด Main • ไม่สามารถประกาศเมธอดภายในเมธอดได้
การประกาศเมธอด • การประกาศเมธอดนั้นมีส่วนสำคัญสองส่วนคือ 1. ส่วนหัวของเมธอด (header) static double Poly(double a, double b, double c, double x) { return a*x*x + b*x + c; } 2. ส่วนตัวของเมธอด (body)
ส่วนหัวของเมธอด (method header) static double Poly(double a, double b, double c, double x) • ส่วนหัวของเมธอดเป็นการประกาศต่อสาธารณะว่ารูปแบบในการใช้งานของเมธอดนี้เป็นอย่างไร • นอกจากนี้ยังเป็นการระบุอย่างไม่เป็นทางการถึงข้อตกลงว่าเมธอดนี้จะทำงานอะไร เช่นในตัวอย่างนี้: เมธอด Poly(double a, double b, double c, double x) คำนวณค่าพนุนามกำลังสอง ax2 + bx + c
ส่วนตัวของเมธอด (method body) • ส่วนหัวของเมธอดเป็นการระบุสัญญาต่อสาธารณะ • ส่วนตัว (body) ของเมธอดระบุโปรแกรมที่ทำงานตามที่สัญญาไว้ --- เป็นรายละเอียดภายในของเมธอด เมธอดอื่น ๆ เมธอด Poly การทำงานจริง ๆ ระบุที่ส่วนตัวของเมธอด เรียกใช้งานตามที่ระบุไว้ ในส่วนหัวของเมธอด
การนำเมธอดไปใช้ • เราสามารถเรียกใช้เมธอดที่นิยามได้จากเมธอดต่าง ๆ ในคลาส public static void Main(string[] args) { double k = 3;double y = Poly(1,2,4,k);Console.WriteLine(y);Console.ReadLine(); }
ความหมายของการเรียกใช้งานเมธอดความหมายของการเรียกใช้งานเมธอด ข้อตกลงของเมธอด การเรียกใช้งาน double y = Poly(1,2,4,k); เมธอด Poly(a, b, c, x) คำนวณค่าพนุนามกำลังสอง ax2 + bx + c ให้ y มีค่าเท่ากับ "ผลการคำนวณค่าพนุนามกำลังสอง 1.k2 + 2.k + 4." ความหมายของการเรียกใช้งานนี้
ตัวอย่างการเรียกใช้งานเมธอด (1) โปรแกรมของเรามี 2 เมธอด คือ Poly ซึ่งเป็นเมธอดย่อย และ Main ซึ่งเป็นโปรแกรมหลัก using System;namespacemet_examples{ class Program { static doublePoly(double a, double b, double c,double x) { return a*x*x + b*x + c; }public static void Main() { double k = 3; double y = Poly(1,2,4,k);Console.WriteLine(y);Console.ReadLine(); } }} เรียกใช้เมธอด Poly ที่นี่ โปรแกรมเริ่มทำงานที่นี่
ตัวอย่างการเรียกใช้งานเมธอด (2) using System;namespacemet_examples{ class Program { static doublePoly(double a, double b, double c,double x) { return a*x*x + b*x + c; }public static void Main() { double k = 3; double y = Poly(1,2,4,k);Console.WriteLine(y);Console.ReadLine(); } }} ค่าของพารามิเตอร์จากจุดที่เรียก ถูกส่งให้กับเมธอด 19 a 1 b 2 k 3 c 4 y 19 x 3 ผลลัพธ์: 19
การส่งพารามิเตอร์ (1) using System;namespacemet_examples{ class Program { static doublePoly(double a, double b, double c,double x) { return a*x*x + b*x + c; }public static void Main() { double k = 3; double y = Poly(1,2,4,k);Console.WriteLine(y);Console.ReadLine(); } }} ขั้นตอนที่สำคัญมากในการเรียกใช้งานเมธอด ก็คือขั้นตอนการส่งพารามิเตอร์
การส่งพารามิเตอร์ (2) static doublePoly(double a, double b, double c,double x) double y = Poly(1,2,4,k); • ในขั้นตอนนี้ พารามิเตอร์ที่เราส่งให้กับเมธอด จะถูก "จับคู่" กับพารามิเตอร์ที่ประกาศไว้ในส่วนหัวของเมธอด
การส่งพารามิเตอร์ (3) static doublePoly(double a, double b, double c,double x) double y = Poly(1,2,4,k); • พารามิเตอร์ทางการ (Formal parameters)คือพารามิเตอร์ที่ประกาศไว้ที่ส่วนหัวของเมธอด • พารามิเตอร์จริง (Actual parameters)คือพารามิเตอร์ที่ส่งให้กับเมธอดจริง ๆ
การส่งพารามิเตอร์ (4) static doublePoly(double a, double b, double c,double x) double y = Poly(1,2,4,k); • ในตัวอย่างข้างต้นนี้ เมื่อมีการเรียกใช้เมธอด สิ่งที่เกิดขึ้นก็คือ ระบบจะคำนวณค่าของพารามิเตอร์จริงทุกตัวให้เสร็จสิ้น จากนั้นจะส่งค่าที่คำนวณได้ให้กับ พารามิเตอร์ทางการในเมธอด
การเรียกใช้งานเมธอด: แบบฝึกหัด 1 using System;namespacemet_examples{ class Program { static doublePoly(double a, double b, double c,double x) { return a*x*x + b*x + c; }public static void Main() { double k = 3; double y = Poly(2,k,k+3,2);Console.WriteLine(y);Console.ReadLine(); } }} ผลลัพธ์ของโปรแกรมนี้คืออะไร? 20
การส่งค่า: เฉลย using System;namespacemet_examples{ class Program { static doublePoly(double a, double b, double c,double x) { return a*x*x + b*x + c; }public static void Main() { double k = 3; double y = Poly(2,k,k+3,2);Console.WriteLine(y);Console.ReadLine(); } }} 2 3 6 2
การส่งพารามิเตอร์แบบ Pass by value • รูปแบบของการส่งพารามิเตอร์ในตัวอย่างข้างต้น ซึ่งเป็นรูปแบบมาตรฐานของ C# เรียกว่าการส่งค่าแบบ Pass by value • นั่นคือ เป็นการส่งพารามิเตอร์ที่ส่งเฉพาะค่า (value) ของพารามิเตอร์จริงให้กับเมธอด • ยังมีรูปแบบอื่น ๆ ในการส่งค่าอีก ซึ่งเราจะได้พิจารณาถัด ๆ ไป
การเรียกใช้งานเมธอด: แบบฝึกหัด 2 using System;namespacemet_examples{ class Program { static doublePoly(double a, double b, double c,double x) { /* ละไว้ */} public static void Main() { double k = 3; double y = Poly(2,k,k+3,2);Console.WriteLine(y); y = Poly(1,1,1,10);Console.WriteLine(y);Console.WriteLine(Poly(1,2,3,2));Console.ReadLine(); } }} ผลลัพธ์ของโปรแกรมนี้คืออะไร? 20111 11
คำสั่ง return(1) static int Min(int x, int y) { if(x < y) return x; return y; } static void Main(string [] args) { int a = int.Parse( Console.ReadLine()); int b = int.Parse( Console.ReadLine()); Console.WriteLine(Min(a,b)); } • รูปแบบ: returnค่า; • คำสั่ง return จะคืนค่ากลับไปยังจุดที่เรียกทันที แม้ว่าจะไม่ใช่คำสั่งสุดท้ายก็ตาม
คำสั่ง return (2) static int Min(int x, int y) { if(x < y) return x; return y; } • คำสั่ง return จะคืนค่ากลับไปยังจุดที่เรียกทันที แม้ว่าจะไม่ใช่คำสั่งสุดท้ายก็ตาม Console.WriteLine( Min(100,15)); x 100 y 15 15
คำสั่ง return (3) static int Min(int x, int y) { if(x < y) return x; return y; } • คำสั่ง return จะคืนค่ากลับไปยังจุดที่เรียกทันที แม้ว่าจะไม่ใช่คำสั่งสุดท้ายก็ตาม Console.WriteLine( Min(10,100)); x 10 y 100 10
เมธอดที่ไม่คืนค่า • ในการแบ่งงานเพื่อมาพัฒนาเป็นเมธอดนั้น หลาย ๆ ครั้งเราพบว่าเมธอดนั้นมีการทำงานที่เสร็จในตัวเอง เช่น พิมพ์ค่าผลลัพธ์ • เมธอดเหล่านั้นมักไม่มีการคืนค่ากลับมายังโปรแกรมในส่วนที่เรียกใช้ ในการประกาศ เราจะระบุแบบชนิดข้อมูลที่เมธอดคืนกลับมาเป็นชนิด void static void PrintLine(int n) { int i = 0; while(i < n) { Console.Write("*"); i++; } Console.WriteLine(); }
คำสั่ง return ในเมธอดที่ไม่คืนค่า • ในทำนองเดียวกับในเมธอดที่คืนค่า คำสั่ง return ในเมธอดที่ไม่คืนค่าทำให้เมธอดจบการทำงาน และคืนการทำงานกลับไปที่จุดที่เรียกเมธอดนั้น
ตัวอย่าง ตัวอย่างการทำงาน class Program { static void Test(int n) {int i = 0;while(true) {Console.WriteLine(i); i++;if(i > n) return; } }public static void Main(string[] args) {int a = int.Parse(Console.ReadLine());Test(a);Console.ReadLine(); } } 3 0 1 2 3 • พิจารณาเมธอด Test และคำสั่ง while • สังเกตว่าคำสั่ง while ดังกล่าวไม่มีทางหยุดการทำงานเอง เนื่องจากเงื่อนไขเป็นจริงตลอดเวลา อย่างไรก็ตามคำสั่ง return ที่จะถูกทำงานเมื่อ i > n จะทำให้เมธอดหยุดทำงาน
ตัวอย่าง: เมธอดเพื่อลดความซ้ำซ้อน • มีโปรโมชั่นโทรศัพท์สองแบบ คือ • แบบ A:จ่ายรายเดือน 50 บาท โทรฟรี 50 นาที จากนั้นคิดนาทีละ 1.5 บาท • แบบ B:จ่ายรายเดือน 150 บาท โทรฟรี 100 นาที หลังจากนั้นคิดนาทีละ 1 บาท • ให้เขียนโปรแกรมรับเวลาที่คาดว่าจะใช้โทรศัพท์จากนั้นให้แนะนำว่าจะใช้โปรโมชั่นใด
public static void Main(string[] args) {Console.Write("Enter expected usage: ");int u = int.Parse(Console.ReadLine());double price1;if(u <= 50) price1 = 50;else price1 = 50 + (u - 50)*1.5;double price2;if(u <= 100) price2 = 150;else price2 = 150 + (u - 100)*1.0;if(price1 < price2)Console.WriteLine("Plan A is better.");elseConsole.WriteLine("Plan B is better.");Console.ReadLine(); } โปรแกรมที่ไม่ใช้เมธอด • พิจารณาส่วนของโปรแกรมที่ใช้คำนวณค่าใช้จ่าย • ส่วนของโปรแกรมนั้นคล้ายกันมาก
ส่วนของโปรแกรมที่คล้ายกันส่วนของโปรแกรมที่คล้ายกัน • พิจารณาส่วนที่เหมือนกัน และต่างกัน • ส่วนที่ต่างกัน สามารถแยกออกมาเป็นพารามิเตอร์ของเมธอดได้ double price1;if(u <= 50) price1 = 50;else price1 = 50 + (u - 50)*1.5; double price2;if(u <= 100) price2 = 150;else price2 = 150 + (u -100)*1.0; ราคาต่อนาทีในส่วนที่เหลือ จำนวนนาทีที่โทรฟรี ค่าใช้จ่ายรายเดือน
เมธอดสำหรับคำนวณ static doubleCalculatePrice(doublemonthlyFee,doublefreeMinutes,double rate,double usage) {if(usage <= freeMinutes) return monthlyFee;else return monthlyFee + (usage - freeMinutes) * rate; } • เราแยกการคำนวณที่เหมือนกันออกมาเป็นเมธอด • สังเกตการตั้งชื่อตัวแปรที่สื่อความหมาย
โปรแกรมหลัก public static void Main(string[] args) {Console.Write("Enter expected usage: ");int u = int.Parse(Console.ReadLine());double price1 = CalculatePrice(50, 50, 1.5, u);double price2 = CalculatePrice(150, 100, 1.0, u);if(price1 < price2)Console.WriteLine("Plan A is better.");elseConsole.WriteLine("Plan B is better.");Console.ReadLine(); } • โปรแกรมหลักก็สั้นลง และอ่านเข้าใจได้ง่ายขึ้น
มุมนักคิด จงเขียนโปรแกรมที่รับจำนวนเต็ม N จากผู้ใช้ แล้วพิมพ์รูปสามเหลี่ยม ขนาด N คอลัมน์ คูณ N บรรทัด ที่ประกอบด้วยตัวอักขระ * Enter N: 3 *** *** Enter N: 4 *** *** **** Enter N: 6 *** *** **** ***** ****** หมายเหตุ:ให้เขียนเมธอด PrintTriangle(int n) ที่พิมพ์สามเหลี่ยมดังกล่าว เมธอด PrintTriangleสามารถเรียกใช้เมธอด PrintLineที่เขียนไว้ก่อนได้
คำแนะนำ • ให้พิจารณาปรับแก้จากเมธอด PrintSquare static void PrintSquare(int n) { int i = 0; while(i < n) { PrintLine(n); i++; } } Enter N: 6 *** *** **** ***** ****** ส่วนใดที่ทำให้ไม่ได้ผลลัพธ์ตามต้องการ?
ตัวแปรของเมธอด เมธอดอื่น ๆ เมธอด Poly • ในการทำงานของเมธอดที่ซับซ้อนมากขึ้น อาจมีความจำเป็นต้องใช้ตัวแปรในการเก็บค่าชั่วคราวระหว่างการทำงาน การทำงานจริง ๆ ระบุที่ส่วนตัวของเมธอด เรียกใช้งานตามที่ระบุไว้ ในส่วนหัวของเมธอด สามารถประกาศตัวแปรในส่วนตัวเมธอดได้
ตัวอย่าง พิจารณาตัวอย่างจากการคำนวณค่าของฟังก์ชันที่ซับซ้อน static doubleMyFunc(double a, double b, double c){double x = 2 * Math.Pow(a,b);double y = c / x;double z = Math.Exp(a + b/c); return y + z;}
ตัวแปรท้องถิ่น (local variables) • ตัวแปรที่เราประกาศภายในเมธอด ซึ่งรวมไปถึงตัวแปรในพารามิเตอร์ทางการด้วย จะรวมเรียกว่าตัวแปรท้องถิ่นของเมธอด(local variable) static doubleMyFunc(double a, double b, double c){double x = 2 * Math.Pow(a,b);double y = c / x;double z = Math.Exp(a + b/c); return y + z;} ตัวแปรท้องถิ่นของเมธอด MyFuncคือ a, b, c, x, y, และ z