คลาสและออบเจ็ค ในภาษา Ruby
ในบทนี้ คุณจะได้เรียนรู้เกี่ยวกับคลาสในภาษา Ruby เราจะพูดเกี่ยวกับการสร้างคลาสและการนำคลาสไปสร้างออบเจ็ค และเราจะอธิบายเกี่ยวกับแนวคิดการเขียนโปรแกรมเชิงวัตถุ (OOP) ซึ่งเป็นรูปแบบของการเขียนโปรแกรมโดยการมองทุกอย่างเป็นวัตถุ ซึ่งจะมีข้อมูลและการกระทำในตัวมันเอง ก่อนเริ่ม มาดูกันก่อนว่าคลาสคืออะไร
คลาสคืออะไร
คลาส (Class) นั้นเป็นแม่แบบที่ใช้สำหรับการสร้างออบเจ็ค ออบเจ็คสามารถประกอบไปด้วยแอททริบิวต์ (Attribute) ซึ่งเป็นข้อมูลที่ใช้อธิบายออบเจ็คนั้นๆ และเมธอดซึ่งเป็นฟังก์ชันการทำงานของออบเจ็ค ซึ่งทั้งสองอย่างนี้นั้นจะถูกกำหนดไว้ในคลาส เมื่อเราสร้างคลาสขึ้นมาแล้ว เราสามารถนำคลาสดังกล่าวไปสร้างเป็นออบเจ็คได้ หรือกล่าวอีกนัยหนึ่ง คลาสเป็นประเภทข้อมูลของออบเจ็ค
การใช้คลาสทำให้เราสามารถใช้แนวคิดการเขียนโปรแกรมเชิงวัตถุเข้ามาช่วยได้ การเขียนโปรแกรมเชิงวัตถุคือการมองทุกอย่างเป็นออบเจ็ค ออบเจ็คจะประกอบไปด้วยข้อมูลและเมธอด และอย่างที่คุณรู้ทุกอย่างในภาษา Ruby นั้นเป็นออบเจ็ค นอกจากนี้ การเขียนโปรแกรมเชิงวัตถุยังมีคุณสมบัติอย่างการสืบทอดและการห่อหุ้มข้อมูล
การสร้างคลาสในภาษา Ruby
อย่างไรก็ตาม เราจะเริ่มต้นกับการสร้างคลาสก่อน ซึ่งเป็นจุดเริ่มต้นของการเขียนโปรแกรมเชิงวัตถุ นี่เป็นรูปแบบการประกาศคลาสในภาษา Ruby
class Name
# Class definition
end
จากรูปแบบการประกาศ เราใช้คำสั่ง class
สำหรับเริ่มต้นการประกาศคลาส และ Name
นั้นเป็นชื่อของคลาส ชื่อของคลาสนั้นต้องเริ่มต้นด้วยตัวพิมพ์ใหญ่และคั่นแต่ละคำด้วยรูปแบบ Camel case และสิ้นสุดการประกาศคลาสด้วยคำสั่ง end
ภายในบล็อคของคลาส จะเป็นการกำหนดแอททริบิวต์และเมธอดของคลาส
ต่อไปเราจะสร้างคลาสของรูปสี่เหลี่ยมและที่สามารถกำหนดความยาวและความสูงได้ และมีเมธอดสำหรับหาพื้นที่ของรูปสี่เหลียมดังกล่าว นี่เป็นตัวอย่างคลาสแรกของเรา
class Rectangle
attr_accessor(:width, :height)
def area
return @width * @height
end
end
# Creating objects
rect = Rectangle.new
rect.width = 2
rect.height = 4
puts "Width: #{rect.width}"
puts "Height: #{rect.height}"
puts "Calculate area: #{rect.area}"
ในตัวอย่าง เราได้สร้างคลาสที่มีชื่อว่า Rectangle
ซึ่งคลาสมีนี้มีแอททริบิวต์สองตัวคือ width
และ height
สำหรับเก็บความยาวและความสูงของออบเจ็คสี่เหลี่ยม และเมธอด area
สำหรับคำนวณหาพื้นที่ของรูปสี่เหลี่ยม
attr_accessor(:width, :height)
คำสั่งแรกที่คุณเห็นภายในคลาสก็คือเราได้เรียกใช้เมธอด attr_accessor
เมธอดนี้ใช้สำหรับกำหนดแอททริบิวต์ให้กับคลาส โดยการระบุชื่อแอททริบิวต์เป็น Symbol ที่เราต้องการให้คลาสมี เราได้ระบุ Symbol :width
และ :height
และเมธอด attr_accessor
จะสร้างสองเมธอดสำหรับกำหนดค่าและรับค่าสำหรับแต่ละแอททริบิวต์
def width=(value)
@width = value
end
def width
return @width
end
def height=(value)
@height= value
end
def height
return @height
end
นี่เป็นสิ่งที่เราได้รับจากการทำงานเบื้องหลังของเมธอด attr_accessor
มันได้สร้างเมธอดสำหรับกำหนดค่าและอ่านค่าของแอททริบิวต์ให้กับเรา ทำให้เราสามารถเข้าถึงแอททริบิวต์จากภายนอกคลาสได้
def area
return @width * @height
end
ต่อมาเรามีเมธอด area
เมธอดนี้ใช้สำหรับคำนวณหาพื้นที่ของรูปสี่เหลี่ยมจากความกว้างและความยาวที่ถูกเก็บในแอททริบิวต์ @width
และ @height
และอย่างที่คุณเห็น เมื่อเราเข้าถึงแอททริบิวต์ภายในคลาส มันจะต้องขึ้นต้นด้วยเครื่องหมาย @
เสมอ
rect = Rectangle.new
หลังจากที่เราสร้างคลาสเสร็จแล้ว เราสามารถนำคลาสไปสร้างออบเจ็คได้ ในตัวอย่างเราได้นำคลาสมาสร้างออบเจ็คโดยการเรียกใช้งานเมธอด new
บนคลาส Rectangle
เมธอดนี้เป็นเมธอดที่มีอยู่ในทุกคลาสในภาษา Ruby มันใช้สร้างออบเจ็คของคลาสดังกล่าว และเรากำหนดออบเจ็คไว้ในตัวแปร rect
rect.width = 2
rect.height = 4
หลังจากที่เราสร้างออบเจ็คแล้ว เราได้กำหนดค่าความยาวและความสูงให้กับออบเจ็คสี่เหลี่ยมของเรา ในทางทฤษฏีแล้ว เราได้เรียกใช้งานเมธอด width=
และ height=
สำหรับกำหนดค่าให้กับแอททริบิวต์ ซึ่งเมธอดเหล่านี้ถูกสร้างโดยเมธอด attr_accessor
ที่เราได้บอกไปก่อนหน้า
puts "Width: #{rect.width}"
puts "Height: #{rect.height}"
puts "Calculate area: #{rect.area}"
หลังจากนั้นเราเรียกใช้งานเมธอด width
และเมธอด height
เพื่อดูความยาวและความสูงที่เราเพิ่งได้กำหนดไป และเรียกใช้เมธอด area
เพื่อคำนวณหาพื้นที่ของรูปสี่เหลี่ยม
Width: 2
Height: 4
Calculate area: 8
นี่เป็นผลลัพธ์การทำงานของโปรแกรม เราได้สร้างคลาสของรูปสี่เหลี่ยมที่เก็บความยาวและความสูง และนำคลาสไปสร้างเป็นออบเจ็คเพื่อใช้งาน
การนำคลาสไปสร้างออบเจ็ค
ในการสร้างคลาสนั้น วัตถุประสงค์ของมันก็คือการนำคลาสไปสร้างเป็นออบเจ็ค ในตัวอย่างก่อนหน้า เราได้สร้างเพียงหนึ่งออบเจ็คสำหรับคลาส Rectangle
อย่างไรก็ตาม เราสามารถนำคลาสไปสร้างออบเจ็คกี่ออบเจ็คก็ได้ ซึ่งนี่เองเป็นแนวคิดของการนำโค้ดกลับมาใช้ใหม่ (Code reuse) นี่เป็นตัวอย่าง
class Rectangle
attr_accessor(:width, :height)
def set_size(w, h)
@width = w
@height = h
end
def show_size
puts "Width: #{@width}, Height: #{@height}"
end
def area
return @width * @height
end
end
# Creaing objects
rect = Rectangle.new
rect.set_size(2, 4)
rect2 = Rectangle.new
rect2.set_size(3, 5)
puts "Rect 1"
rect.show_size
puts "Area: #{rect.area}"
puts "Rect 2"
rect2.show_size
puts "Area: #{rect2.area}"
ในตัวอย่าง เราได้ใช้คลาส Rectangle
จากในตัวอย่างก่อนหน้า แต่สำหรับคลาสในตัวอย่างนี้เราได้เพิ่มเมธอด set_size
และเมธอด show_size
เข้ามา
def set_size(w, h)
@width = w
@height = h
end
เมธอด set_size
นั้นเป็นเมธอดที่ใช้สำหรับกำหนดความยาวและความกว้างให้กับออบเจ็ค ซึ่งเมธอดนี้มีอาร์กิวเมนต์สองตัวที่รับเข้ามาคือ w
และ h
สำหรับกำหนดความยาวและความสูงให้กับแอททริบิวต์ @width
และ @height
เราสร้างเมธอดนี้ขึ้นมาเนื่องจากเราไม่ต้องการกำหนดแอททริบิวต์ทีละค่าเหมือนในตัวอย่างก่อนหน้า
def show_size
puts "Width: #{@width}, Height: #{@height}"
end
ต่อมาเป็นเมธอด show_size
เมธอดนี้ใช้สำหรับแสดงขนาดของออบเจ็ค ซึ่งเป็นความยาวและความสูงนั่นเอง โดยการใช้เมธอดนี้ทำให้เราไม่จำเป็นต้องเขียนโค้ดการแสดงผลเป็นจำนวนมากที่ภายนอกคลาสเหมือนในตัวอย่างก่อนหน้า
rect = Rectangle.new
rect.set_size(2, 4)
rect2 = Rectangle.new
rect2.set_size(3, 5)
หลังจากนั้นเราได้นำคลาสมาสร้างออบเจ็ค ในคราวนี้เราได้สร้างสองออบเจ็คได้แก่ rect
และ rect2
ซึ่งเมื่อทั้งสองออบเจ็คถูกสร้าง มันจะมีแอททริบิวต์และเมธอดเป็นของมันเอง เราได้เรียกเมธอด set_size
สำหรับกำหนดขนาดให้แต่ละออบเจ็ค
puts "Rect 1"
rect.show_size
puts "Area: #{rect.area}"
หลังจากนั้นเราแสดงรายละเอียดเกี่ยวกับออบเจ็คด้วยเมธอด show_size
และอย่างที่คุณเห็น เมื่อเราเรียกใช้เมธอด การแสดงผลจะขึ้นอยู่กับแอททริบิวต์ของออบเจ็คนั้นๆ นี่แสดงให้เห็นว่าออบเจ็คที่สร้างจากคลาสเดียวกัน แต่มันมีแอททริบิวต์และเมธอดเป็นของมันเอง นี่ทำให้เราสามารถใช้โค้ดภายในคลาสกับออบเจ็คเป็นจำนวนเท่าไหร่ก็ได้
Rect 1
Width: 2, Height: 4
Area: 8
Rect 2
Width: 3, Height: 5
Area: 15
นี่เป็นผลลัพธ์การทำงานของโปรแกรมจากการรันตัวอย่างสำหรับการนำคลาสมาสร้างเป็นออบเจ็คในภาษา Ruby
คอนสตรัคเตอร์ของคลาส
คอนสตรัคเตอร์นั้นเป็นเมธอดพิเศษที่ใช้สำหรับกำหนดเพื่อให้ทำงานบางอย่างในตอนที่ออบเจ็คถูกสร้าง ยกตัวอย่าง เช่น การกำหนดค่าเริ่มต้นให้กับออบเจ็ค โดยในภาษา Ruby นั้นคอนสตรัคเตอร์เมธอดต้องมีชื่อว่า initialize
เสมอ มันสามารถรับอาร์กิวเมนต์ได้เหมือนกับเมธอดปกติ โดยทั่วไปแล้วเมธอดนี้จะถูกเรียกใช้งานเมื่อเราสร้างออบเจ็คด้วยเมธอด new
ของคลาสใดๆ
ต่อไปเป็นตัวอย่างสำหรับการประกาศคอนสตรัคเตอร์เมธอดให้กับคลาส เราจะสร้างคลาส Book
ซึ่งเป็นคลาสของหนังสือ
class Book
attr_accessor(:name, :author, :year)
def initialize(name, author, year)
@name = name
@author = author
@year = year
end
def info
puts "#{@name} by #{@author}, published in #{@year}"
end
def year_passed
return Time.now.year - @year
end
end
b1 = Book.new('C Programming', 'Dennis Ritchie', 1972)
b2 = Book.new('Python Programming', 'Guido van Rossum', 1990)
b3 = Book.new('Ruby Programming', 'Yukihiro Matsumoto', 1995)
puts "List of books"
b1.info
b2.info
b3.info
puts "\nHow long Ruby programming book published?"
puts "Answer: #{b3.year_passed} years ago"
ในตัวอย่าง เราได้สร้างคลาสที่มีชื่อว่า Book
คลาสนี้ประกอบไปด้วยแอททริบิวต์สามตัวคือ name
สำหรับเก็บชื่อของหนังสือ author
สำหรับเก็บชื่อของผู้เขียนหนังสือ และ year
สำหรับเก็บปีที่หนังสือถูกเผยแพร่ เราได้ระบุแอททริบิวต์เหล่านี้ด้วยเมธอด attr_accessor
def initialize(name, author, year)
@name = name
@author = author
@year = year
end
ภายในเมธอด initialize
ซึ่งเป็นคอนสตรัคเตอร์ของคลาสของเรา นั้นรับสามอาร์กิวเมนต์และนำอาร์กิวเมนต์เหล่านั้นกำหนดเป็นชื่อของหนังสือ ชื่อผู้เขียน และปีที่เผยแพร่ตามลำดับ หรือจะกล่าวอีกนัยหนึ่งก็คือเราใช้เมธอดนี้สำหรับกำหนดค่าเริ่มต้นให้กับออบเจ็ค ซึ่งเมธอดนี้จะถูกเรียกใช้งานในตอนที่ออบเจ็คถูกสร้าง
def info
puts "#{@name} by #{@author}, published in #{@year}"
end
ต่อมาเมธอด info
เมธอดนี้ใช้สำหรับแสดงรายละเอียดของหนังสือที่ประกอบไปด้วย ชื่อหนังสือ ชื่อผู้เขียน และปีที่เผยแพร่ เราสามารถเรียกใช้งานเมธอดนี้เพื่อแสดงรายละเอียดของหนังสือได้โดยตรงเหมือนกับที่คุณเห็นในตัวอย่างก่อนหน้า
def year_passed
return Time.now.year - @year
end
และเมธอดสุดท้าย year_passed
เมธอดนี้ใช้สำหรับคำนวณหาว่าหนังสือได้เผยแพร่ไปนานเท่าไหร่แล้ว เราใช้เมธอดนี้ในกรณีที่เราต้องการทราบว่าเวลาผ่านไปนานเท่าไหร่ โดยการนำปีที่เผยแพร่ไปลบออกจากปีปัจจุบัน ซึ่งคำสั่ง Time.now.year
นั้นใช้สำหรับรับค่าปีปัจจุบันในคอมพิวเตอร์ของเรา
b1 = Book.new('C Programming', 'Dennis Ritchie', 1972)
b2 = Book.new('Python Programming', 'Guido van Rossum', 1990)
b3 = Book.new('Ruby Programming', 'Yukihiro Matsumoto', 1995)
หลังจากที่เราได้ประกาศคลาสเสร็จเรียบร้อยแล้ว เราได้นำคลาสมาสร้างออบเจ็คสามออบเจ็ค สังเกตว่าในตอนสร้างออบเจ็คเราสามารถกำหนดค่าให้กับออบเจ็คผ่านทางเมธอด new
ได้เลย ซึ่งค่าเหล่านี้จะถูกส่งผ่านเข้าไปยังเมธอด initialize
ซึ่งเป็นคอนสตรัคเตอร์ของคลาสนั่นเอง
puts "List of books"
b1.info
b2.info
b3.info
หลังจากที่สร้างออบเจ็คเรียบร้อยแล้ว เราได้เรียกใช้งานเมธอด info
บนตัวแปรออบเจ็คเหล่านั้นเพื่อแสดงรายละเอียดของหนังสือ นี่แสดงให้เห็นว่าเราไม่จำเป็นต้องเขียนโค้ดการแสดงผลทุกครั้งสำหรับแต่ละออบเจ็ค แต่เขียนเป็นเมธอดของออบเจ็คแทน ซึ่งผลลัพธ์ที่ได้นั้นจะขึ้นอยู่กับค่าแอททริบิวต์ของแต่ละออบเจ็ค
puts "\nHow long Ruby programming book published?"
puts "Answer: #{b3.year_passed} years ago"
และในสองคำสั่งสุดท้ายนั้นเราต้องการทราบว่าหนังสือภาษา Ruby นั้นถูกเผยแพร่มาแล้วเป็นเวลากี่ปี เราสามารถใช้เมธอด year_passed
สำหรับรับค่าเวลาที่ผ่านไปเป็นปีได้
List of books
C Programming by Dennis Ritchie, published in 1972
Python Programming by Guido van Rossum, published in 1990
Ruby Programming by Yukihiro Matsumoto, published in 1995
How long Ruby programming book published?
Answer: 25 years ago
นี่เป็นผลลัพธ์การทำงานของโปรแกรมสำหรับการใช้งานคอนสตรัคเตอร์ คุณจะเห็นได้ว่าการใช้คอนสตรัคเตอร์นั้นจะทำให้เราสามารถกำหนดค่าให้กับออบเจ็คในตอนที่สร้างออบเจ็คได้เลย ซึ่งถ้าหากเราไม่ใช้คอนสตรัคเตอร์ จะทำให้เราต้องกำหนดค่าให้กับออบเจ็คทีละค่าดังในตัวอย่างด้านล่างนี้
b1 = Book.new
b1.name = 'C Programming'
b1.author = 'Dennis Ritchie'
b1.year = 1972
ในบทนี้ คุณได้เรียนรู้เกี่ยวกับคลาสในภาษา Ruby เราได้พูดถึงการสร้างคลาสและการนำคลาสไปสร้างออบเจ็คสำหรับใช้งานในโปรแกรม นอกจากนี้ เราได้พูดคอนสตรัคเตอร์ของคลาสซึ่งเป็นเมธอดพิเศษที่จะถูกเรียกในตอนที่ออบเจ็คถูกสร้าง
ในตอนนี้คุณคงพอจะเห็นภาพแล้วว่าการใช้คลาสนั้นทำให้เราสามารถนำโค้ดกลับมาใช้ใหม่ได้ โดยการนำไปสร้างเป็นออบเจ็คเป็นจำนวนเท่าไหร่ก็ได้ ซึ่งออบเจ็คเหล่านั้นใช้โค้ดจากคลาสเดียวกัน แต่แตกต่างกันที่ข้อมูลและการทำงานของเมธอด ซึ่งนี่เองเป็นแนวคิดของการเขียนโปรแกรมเชิงวัตถุ