เรื่องที่ควรรู้และทำความเข้าใจกันก่อนที่จะเริ่มเขียนภาษา Ruby
แต่ละหัวข้อที่เขียนนั้ผมไม่ได้เรียงลำดับตามความสำคัญนะครับ แบบว่า คิดอะไรได้ก่อนก็ว่าไปก่อน ถึงแม้เนื้อหาจะค่อนข้างเบาบางออกแนว งงๆ แต่อย่างน้อยมันก็น่าจะช่วยให้เพื่อนรู้จักภาษา Ruby ได้มากขึ้นบ้างล่ะน่า
มาลองไล่ดูกันไปทีละข้อครับ
1) Ruby เป็นภาษาที่ทำงานในแบบ OOP (Object Oriented Programming)
ตามที่จั่วหัวไว้เลยครับ Ruby ถูกสร้างขึ้นด้วยความตั้งใจที่จะให้เป็นภาษาที่ทำงานแบบ OOP อย่างเต็มรูปแบบ
ดังนั้นการทำงานของ Ruby ในทุกๆส่วน จึงเป็นการทำงานที่ต้องเกี่ยวกับอ็อบเจกต์ทั้งสิ้น โครงสร้างหรือข้อมูลพื้นฐานต่างๆ ใน Ruby ก็เป็นอ็อบเจกต์เช่นกัน ข้อมูลพื้นๆ ที่คุณอาจเจอในภาษา programming อื่นๆ อย่าง String, Integer, Floating point, Array, Boolean หรือ แม้กระทั่งค่าว่างอย่าง nil เหล่านี้เป็นอ็อบเจกต์หมด
แล้วยังไง ?
ก็สบายสิครับ เพราะหากว่าข้อมูลพื้นฐานล้วนเป็นอ็อบเจกต์กันหมด นั้นหมายความว่ามันต้องมีคลาสของข้อมูลชนิดนั้นๆ (หรือของอ็อบเจกต์นั้นๆ) ถูกกำหนดไว้ในภาษา Ruby ด้วย ซึ่งคลาสพื้นฐานเหล่านี้ติดมาพร้อมกับภาษา Ruby เรียบร้อยแล้ว ในรูปของ (Build-in class) ทำให้เราสามารถเรียกใช้ความสามารถของอ็อบเจกต์แต่ละชนิดจากเมธอดที่มาพร้อมกับคลาสได้เลย
ตัวอย่างความสามารถพื้นๆ ของข้อมูลในแต่ละประเภท
เมื่อทดลองรันผ่าน irb จะได้ผลประมาณนี้
"This is Ruby world!".upcase # => THIS IS RUBY WORLD!
"This is Ruby world!".size # => 19
text = "This is Ruby world!"
text.gsub(/world/, "land") # => This is Ruby land!
text.reverse # => !dlrow ybuR si sihT
13*2 # => 26
13.to_s # => "13"
3.times { |t| print "#{t} " }
# => shows "0 1 2" and return 3
text.class # => String
3.class # => Fixnum
true.class # => TrueClass
nil.class # => NilClass
ย้ำอีกครั้งว่า ข้อมูลแต่ละตัวมันเป็นอ็อบเจกต์ในตัวของมันเองอยู่แล้ว (ข้อมูลพื้นฐานเหล่านี้ไม่จำเป็นต้องสร้างอ็อบเจกต์จากคลาสโดบใช้ new เหมือนอ็อบเจกต์ทั่วๆ ไป เพราะตัวแปรภาษา Ruby จะจัดการให้เอง แต่ขอให้มองว่ามันเป็นอ็อบเจกต์ตัวหนึ่ง) ดังนั้นเราจึงสามารถเรียกเมธอดออกมาใช้ผ่านทางอ็อบเจกต์นั้นได้เลย
Ruby มีสิ่งที่เรียกว่า module ซึ่ง ทำหน้าที่ระบุความสามารถเฉพาะในลักษณะใดลักษณะหนึ่ง โดยเราสามารถนำความสามารถที่กำหนดไว้เป็น module เข้ามา "ผสม (mix-in)" ลงไปในคลาสเพื่อให้คลาสมีความสามารถแบบเดียวกับที่ระบุไว้ใน module ด้วย
เราสามารถนำ module มาประยุกต์ใช้เพื่อให้ คลาส เสมือนมีความสามารถของการสืบทอดคุณสมบัติจากคลาสมากกว่าหนึ่งคลาส (multiple inheritance) นอกจากนี้ยังใช้ module เพื่อแบ่งแยกหมวดหมู่ของคลาสแต่และคลาสให้ชัดเจน (namespacomg) ได้ด้วย
การนำ module มาใช้ก็ง่ายมากเพราะหน้าตาเหมือนคลาสเลย เพียงแต่มันไม่สามารถที่จะใช้สร้างอ็อบเจกต์ได้เท่านั้นเอง รายละเอียดของ module ผมขอเก็บไว้พูดถึงคราวหลัง
2) Dynamic type: ไม่ต้องกำหนดชนิดของตัวแปร
อย่างที่เข้าใจกันว่า ตัวแปรคือสิ่งสมมติที่เรานำมาใช้ในการอ้างอิงถึงข้อมูลตัวใดตัวหนึ่ง เวลาเราจะนำข้อมูลไปใช้เพื่อคำนวณหรือกระทำการใดๆเราก็จะอ้างอิงถึงตัวแปรที่เก็บข้อมูลนั้นๆอยู่แทน
ข้อมูลที่พูดถึงก็มีอยู่ด้วยกันหลายประเภทครับ เช่น สตริง เลขจำนวนเต็ม เลขทศนิยม เป็นต้น
เพื่อให้คนเขียนโปรแกรมและตัวภาษาไม่งง และป้องกันข้อผิดพลาดที่อาจเกิดขึ้นจากการคำนวณด้วย แปรคนละชนิด ภาษาอย่าง Java หรือ C# จึงมีข้อกำหนดว่า ก่อนที่จะนำตัวแปรมาใช้ เราจะต้องประกาศตัวแปรกันก่อนเพื่อให้รู้ว่าตัวแปรตัวนั้นๆใช้เก็บข้อมูลประเภทไหน จะได้ไม่นำมาใช้มั่วกัน คนเขียนโปรแกรมจะเป็นคนรับผิดชอบในการกำหนดค่าให้กับข้อมูลแต่ละประเภทแต่ละตัว
เราเรียกลักษณะเช่นนี้ว่าเป็นการทำงานแบบ static type
การประกาศตัวแปรทำได้โดยการเขียนชื่อประเภทของข้อมูลไว้หน้าชื่อของตัวแปรในครั้งแรกที่เราสร้างตัวแปรนั้นขึ้นมา
ตัวอย่างการประกาศตัวแปรในภาษา C# หรือ Java สามารถเขียนได้ดังนี้
int a;
int b;
int sum;
a = 10;
b = 15;
sum = a + b;
ทีนี้กลับมาดูทางฝั่งภาษา Ruby บ้าง
ภาษา Ruby เป็น Dynamic type การจัดการกับประเภทของข้อมูลจะตรงข้ามกับ Static type
เราจะไม่เห็นการประกาศตัวแปรเพื่อกำหนดประเภทของข้อมูลเหมือนกับตัวอย่างที่ผ่านมา เพราะภาษา Ruby จะจัดการกับประเภทข้อมูลของตัวแปรให้เราโดยอัตโนมัติ เรามีหน้าที่แค่สร้างและนำตัวแปรไปใช้ให้ถูกต้องเท่านั้น ไม่ต้องไปกำหนดให้มัน
โค้ดแบบเดียวกับตัวอย่างที่ผ่านมาจึงเขียนใหม่ได้ดังนี้
# Ruby code
a = 10
b = 15
sum = a + b # => 25
จะเห็นว่าเราไม่ต้องประกาศประเภทของตัวแปร a และ b อีก สามารถนำไปใช้เก็บค่าของข้อมูลได้เลย
(ในที่นี้ตัวแปร a และ b จะเก็บค่าเลขจำนวนเต็ม)
นอกจากนี้ ตัวแปรตัวเดียวกันสามารถใช้เก็บข้อมูลคนละประเภทกันได้ด้วย
Ruby จะรู้เองโดยอัตโนมัติว่าในขณะนั้นตัวแปรตัวเก็บข้อมูลประเภทไหนอยู่ ซึ่งทำให้ Ruby นำตัวแปรไปใข้ได้อย่างถูกต้อง
a = 10
puts a # => 10
a = "ten"
puts a # => ten
การแปลงค่าจากตัวแปรประเภทหนึ่งไปเป็นตัวแปรอีกประเภทหนึ่ง (type casting) ไม่ได้เป็นเรื่องยากเย็นสำหรับ Ruby
การแปลงจากสตริงไปเป็นตัวเลข, ตัวเลขเป็นสตริง หรือสตริงเป็นอาเรย์ นั้ค่อนข้าวจะชิวทีเดียว
ลองดูผลลัพธ์ของการแปลงค่าจากตัวอย่างข้างล่างดูครับ
100.to_s # => "100"
"1234".to_i # => 1234
"1234".to_f # => 1234.0
"one two three".split # => ["one", "two", "three"]
[1,2,3].to_s.inspect # => "[1,2,3]"
อย่างไรก็ตามเพื่อให้คนเขียนโปรแกรมไม่งง ว่าอันไหนเป็นตัวแปรอันไหนเป็นข้อมูล ภาษา Ruby จึงมีกฏเกณในการจำแนกประเภทของข้อมูลง่ายๆ ดังนี้ครับ
3) รันโค้ด Ruby ในแบบ procedure programming ได้ ไม่ต้องสร้างฟังชั่น main ก็ได้
ถึงแม้ว่าภาษา Ruby จะเป็น OOP ทั้งแท่ง แต่เราสามารถกำหนดให้มันรันโค้ดในลักษณะเดียวกับ Procedure programming ได้ด้วย คือรันแบบลุยไปเรื่อยทีบรรทัดต่อบรรทัด
อัน นี้จะสะดวกมากเวลาที่เราต้องการทดสอบโค้ด หรือต้องการทดลองร่างโค้ดแบบ Top-down เพราะเราไม่จำเป็นต้องไปสร้างคลาสแล้วเริ่มรันโปรแกรมจาก main เหมือนกับภาษาอื่นๆเขียนโค้ดปุ๊บก็รันแล้วดูผลลัพธ์กันเลย
ลองเปรียบเทียบโค้ดโปรแกรม hello ระหว่าง java และ ruby ดู
ถ้าเป็น Java โค้ดที่จะเริ่มรันต้องอยู่ในเมธอด main ของคลาสที่เราสร้างขึ้นมาก่อน
class HelloWorldApp {
public static void main(String[] args) {
System.out.println("Hello World!"); // Display the string.
}
}
แต่ถ้าเป็น Ruby เราไม่ต้องสร้างคลาสก็ได้ (ทุกอย่างเป็นอ็อบเจกต์และคลาสถูกกำหนดไว้ก่อนในฉากหลังแล้ว) เพียงเขียนโค้ดลงในซอร์ซไฟล์แล้วรันเลย
puts "Hello World!"
อย่างไรก็ตามการจะเขียนโค้ดด้วยรูปแบบใดนั้น ขึ้นอยู่กับความเหมาะสมในการนำโค้ดนั้นไปใช้งานเป็นหลัก ซึ่งเป็นจุดที่ต้องคำนึงถึงอับดับแรก
4) การจำแนกตัวแปรประเภทต่างๆ ใน Ruby
ถึงแม้ว่า Ruby จะเป็น Dynamic type ไม่ต้องประกาศตัวแปร แต่เราเองก็ต้องจำแนกแยกแยะให้ได้ว่า สิ่งที่ปรากฏอยู่ในโค้ด Ruby นั้นเป็นข้อมูล, ตัวแปร, เมธอด หรือคลาส
วิธีดูและแยกข้อมูลหรือตัวแปรในโค้ดให้ออกนั้นไม่ยาก มีหลักการง่ายๆ ดังนี้
- อะไรก็ตามที่อยู่ภายใต้เครื่องหมายคำพูด(" ") หรือเครื่องหมาย (' ') ให้ถือว่ามันคือข้อมูลประเภทสตริง (String) เช่น "a", "hello", "Arsenal"
- ตัวเลขที่ไม่มีจุดทศนิยมถือว่าเป็นข้อมูลประเภทเลขจำนวนเต็ม(Integer) เช่น 3, 25670 โดยเลขจำนวนเต็มใน Ruby เป็นอ็อบเจกต์ของคลาส Fixnum
- ตัวเลขที่มีจุดทศนิยมถือว่าเป็นข้อมูลประเภทเลขทศนิยม(Floating point) เช่น 3.141, 0.0005 โดยตัวเลขทศนิยมเป็นอ็อบเจกต์ของคลาส Float
- สิ่งที่อยู่ในเครื่องหมาย "[ , ]" จะถือว่าเป็นข้อมูลประเภทอาเรย์(Array) เช่น ["one", "two"] หรือ [1,2,3]
- ข้อมูลที่อยู่ในอาเรย์ไม่จำเป็นต้องเป็นข้อมูลชนิดเดียวกันหมด ข้อมูลต่างชนิดกันสามารถปนกันอยู่ในอาเรย์ตัวเดียวได้ด้วย (แน่อนว่าเป็น dynamic type ) เช่น [1, "two", 3.00]
- ตัวเลขที่อยู่ภายในเครื่องหมาย "( )" จะถือว่าเป็นข้อมูลประเภท range เช่น (0..9)
- สิ่งที่อยู่ในเครื่องหมาย {} คือข้อมูลประเภท hash โดยใช้เครื่องหมาย => เป็นตัวขั้นระหว่างค่าของ key และ value เช่น {1=>"one", 2 =>"two", 3=>"three"}
- ตัวอักษร (character) หรือคำ (word) ที่ขึ้นต้นด้วยตัวพิมพ์เล็ก อาจเป็นตัวแปร local หรือเมธอดก็ได้ ไม่ว่ามันจะเป็นตัวแปรหรือเมธอดให้มองไว้ว่าจะมีค่าบางค่าออกมาจากตัวมันแน่ นอน ตัวอย่างเช่น a, count, price_list, email
- ตัวอักษรหรือคำที่อยู่หลังเครื่องหมาย ":" ถือว่าเป็นข้อมูลประเภท symbol เช่น :physic, :school
ที่พูดถึงข้างต้นเป็นเพียงตัวอย่างของข้อมูลเบื้องต้น เพื่อให้เราสามารถแยกแยะพวกมันได้ก่อนเวลาอ่านโค้ดเท่านั้น ยังมีรายละเอียดอื่นๆ อีกมาก เช่น การกำหนดข้อมูล และการนำข้อมูลแต่ละชนิดมาใช้ ซึ่งเราจะหาโอกาสเอามาพูดถึงต่อไป
5) Comment ในภาษา Ruby
Comment คือข้อความที่เราต้องการเขียนแทรกเอาไว้ในโค้ดเพื่ออธิบายการทำงานของโค้ดหรือเอาไว้ใส่ข้อความเพื่อเตือนความจำเวลาแก้ไขโค้ด ซึ่งข้อความที่เป็น comment นั้นจะไม่ถูกแปลรวมไปกับโค้ดเวลารันโปรแกรม
การใส่ comment ในภาษา Ruby ทำได้ 2 แบบคือ
1. ใช้เครื่องหมาย "#" วางไว้หน้าข้อความที่เราต้องการให้เป็น comment โดยจะสามารถใช้เครื่องหมาย "#" กับข้อความที่มีความยาวไม่เกินหนึ่งบรรทัดเท่านั้น
2. ใช้สัญลักษณ์ "=begin" และ "=end" ครอบข้อความที่เราต้องการให้เป็น comment โดยวิธีนี้จะสามารถใช้กับข้อความที่มีความยาวมากกว่า 1 บรรทัดขึ้นไปได้
5) ภาษา Ruby มีตัวแปลภาษาเป็นแบบ Interpreter
หมายความว่าลักษณะการแปลซอร์ซโค้ดของตัวแปลภาษา Ruby จะแปลโค้ดทีละบรรทัด โดยเริ่มจากบรรทัดแรกไปจนถึงบรรทัดสุดท้าย
THX4
ตอบลบเหอะ เหอะ
ตอบลบแล้วภาษาชีนิ ไม่ต้องแปรทีละ บรรทัดหรอ?
ตอบลบแล้วภาษาชีนิ ไม่ต้องแปรทีละ บรรทัดหรอ?
ตอบลบ