ผมพบว่าการใช้ ruby ในการเรียนรู้เรื่อง OOP เป็นเรื่องที่สนุกทีเดียว ทุกอย่างในภาษานี้เป็น Object ไปหมด แม้แต่ nil ยังเป็น object ด้วย ในตอนแรกผมมุ่งศึกษาตัว Rails เป็นหลัก และพบว่าหากไม่ใช่ Ruby แล้ว Rails คงเกิดได้ยากมาก
หากต้องการศึกษา rails ให้มากกว่านี้ผมต้องแม่นเรื่อง Object ของ Ruby ให้มากขึ้น และบทความนี้ผมจะใช้สำหรับเป็น Reference ของตัวเอง

ทดลองสร้าง Class Circle เพื่อเป็นพิมพ์เขียวให้กับ Object circle
#circle.rb
class Circle
@@count
@radious
@circle
end
puts Circle.class_variables #=> @@count
puts Circle.instance_variables #=> @circle@radious
puts Circle.count #=> undefined method `count'
@@count เป็นตัวแปรของ class หรือเรียกว่า class variable
ส่วน @radious และ @circle เป็นตัวแปรของ object เมื่อ object ถูกสร้างขึ้น หรือเรียกว่า instance variable
ซึ่งจะอธิบายความแตกต่างอีกทีหนึ่ง
สังเกตุ error ของบรรทัดสุดท้าย เราจะพบว่า ruby ไม่สามารถอ้างอิงไปที่ตัวแปรโดยตรง แต่จะถามหา method เลย แปลว่าทุกอย่างต้องผ่าน method
ที่นี้ลองสร้าง method สำหรับแก้ไขตัวแปร @radious
#circle.rb
class Circle
def radious=(r)
@radious = r
end
def radious
return @radious
end
end
circle = Circle.new
puts circle.radious #=> nil
circle.radious = 4
puts circle.radious #=> 4
เนื่องจาก ruby เป็นภาษาแบบ dynamic การให้โปรแกรมเขียนโปรแกรมจึงเป็นเรื่องปกติมากๆ เช่นในกรณีนี้เราจะมีคำสั่ง
attr_reader :radious ใช้เขียนคำสั่ง def radious ...
attr_writer :radious ใช้เขียนคำสั่ง def radious=(r) ...
attr_accessor :radious ใช้คำสั่งเดียวเขียนสองคำสั่งข้างบนเลยครับ
#circle.rb
class Circle
attr_accessor :radious
end
กลับมาดูความแตกต่างของ class variable และ instance variable โดยดูจากตัวอย่าง
class Circle
attr_accessor :radious
def count=(c)
@@count = c
end
def count
@@count
end
end
circle_1 = Circle.new
circle_2 = Circle.new
circle_1.radious = 1
circle_2.radious = 2
puts circle_1.radious #=> 1
puts circle_2.radious #=> 2
circle_1.count = 1
circle_2.count = 2
puts circle_1.count #=> 2
puts circle_2.count #=> 2
จากการทดลองเราพบว่า circle_1 และ circle_2 จะใช้ class_variable ร่วมกัน เมื่อแก้ค่า count ที่ circle_1 หรือ circle_2 ค่าจึงออกมาเป็นแบบเดียว
puts Circle.class_variables #=> @@count
puts Circle.instance_variables #=> nil
puts circle_1.instance_variables #=> @radious
จากการทดลองต่อมา เราจะไม่พบ instance_variables เนื่องจาก @radious จะเกิดขึ้นก็ต่อเมื่อมีการเรียกใช้ method radious = แล้วเท่านั้น
ปัญหาต่อมาคือ เราไม่สามารถรู้จำนวนวงกลม ถ้าเราไม่ประกาศ circle ขึ้นมาซักหนึ่งอันก่อน
ทางแก้คือทำให้ method count กลายเป็น class method โดยใส่คำว่า self ลงไป
class Circle
attr_accessor :radious
def count=(c)
@@count = c
end
def self.count
@@count
end
end
circle_1 = Circle.new
circle_1.count = 2
puts Circle.count #=> 2
จะเห็นว่าเราสามารถรู้ค่าของ count ได้โดยไม่ต้องประกาศ circle ขึ้นมาอีกตัว
ถ้าต้องการให้ ruby เขียน code แทนให้ลองทำแบบนี้ครับ
class Circle
attr_accessor :radious
class << self;
attr_accessor :count
end
end
แบบนี้ทั้ง count และ count= จะเป็น class variable ทั้งคู่
สรุปว่าตอนนี้ ruby ของเรามี
* **class variable** เป็นตัวแปรของ class ทุก instance จะใช้ตัวแปรนี้ร่วมกัน
* **class method** เป็น method ของ class เช่นเดียวกับ class variable
* **instance variable** เป็นตัวแปรที่จะใช้ได้เมื่อ class ถูกประกาศขึ้นมาแล้ว
* **instance method** ใช้ได้แบบเดียวกับ instance variable
เลือกใช้งานกันตามความเหมาะสมนะครับ