Ruby:Instance Variables
From Blognone
หลังจากที่เราได้ Class BankAccount จากบทที่แล้ว เรามาลองเรียก balance ออกมาจาก method Bank account ดู
my_account = BankAccount.new('Russ') puts(my_account.balance)
เราจะเจอ error ว่า
account.rb:8: undefined method 'balance' ... (NoMethodError)
แปลว่าแทนที่มันจะไปหาตัวแปล balance มันกลับไปตามหา method balance แทน ... ไม่ต้องทดลอง my_account.@balance นะครับ ตัวแปลใน rails ไม่สามารถเรียกใช้โดยตรงได้จากนอก object
แล้วถ้าต้องการเรียกใช้ตัวแปลจากนอก object สิ่งที่ต้องทำคือกำหนด accessor method ให้กับตัวแปล
def balance @balance end
สิ่งสุดท้ายที่ method balance ทำคือค่า @balance ดังนั้นสิ่งที่ return ออกมาคือ @balance หากทดลองเรียบกใช้แบบเดิม
my_account = BankAccount.new('Russ') puts(my_account.balance)
Ruby จะแสดงค่า @balance ออกมาอย่างถูกต้อง ... แล้วถ้าต้องการกำหนดค่าให้กับ @balance ล่ะ?
def set_balance(new_balance) @balance = new_balance end
set_balance สามารถทำงานได้ดีเยี่ยมเหมือน method balance
my_account.set_balance(100)
ปัญหาคือมันไม่สวยและดูไม่เป็นธรรมชาติ มันจะดีกว่านี้ถ้าเป็น
my_account.balance = 100
ทำอย่างไรเราถึงจะสามารถสร้าง method ให้เป็นธรรมชาติและ ได้คุณสมบัติ encapsulation ไปพร้อมๆ กัน
def balance=(new_balance) @balance = new_balance end
เปลี่ยนชื่อ method โดยใส่ "=" ลงไป
my_account.balance=(100)
หรือ
my_account.balance= 100
หรือ
my_account.balance = 100
ถ้าไม่ต้องการจ้างคนมาเขียน set, get จำนวนมาก Ruby มีคำสั่ง attr_accessor ซึ่งจะช่วยสร้าง set และ get ในแบบที่เราพูดถึงข้างต้น
attr_accessor :balanceวิธีนี้ช่วยลด method ได้หลายบรรทัดทีเดียว หรือจะใช้ทีละหลายๆ ตัวแปลก็ได้
attr_accessor :balance, :grace, :agility
และในกรณีที่ต้องการให้อ่านอย่างเดียวให้ใช้ attr_reader
attr_reader :nameทีนี้ลองเดาว่า attr_writer ใช้ทำอะไร