ฉันมีช่วงเวลาที่ยากในการทำความเข้าใจattr_accessor
ในทับทิม
มีคนอธิบายเรื่องนี้กับฉันได้ไหม
git
attr_accessor
Git เป็นซอฟต์แวร์การควบคุมเวอร์ชันในขณะที่attr_accessor
เป็นวิธีการในรูบี
ฉันมีช่วงเวลาที่ยากในการทำความเข้าใจattr_accessor
ในทับทิม
มีคนอธิบายเรื่องนี้กับฉันได้ไหม
git
attr_accessor
Git เป็นซอฟต์แวร์การควบคุมเวอร์ชันในขณะที่attr_accessor
เป็นวิธีการในรูบี
คำตอบ:
Person
สมมติว่าคุณได้เรียน
class Person
end
person = Person.new
person.name # => no method error
name
เห็นได้ชัดว่าวิธีการที่เราไม่เคยกำหนดไว้ มาทำกันเถอะ
class Person
def name
@name # simply returning an instance variable @name
end
end
person = Person.new
person.name # => nil
person.name = "Dennis" # => no method error
อ่าเราสามารถอ่านชื่อได้ แต่นั่นไม่ได้หมายความว่าเราสามารถกำหนดชื่อได้ นั่นเป็นสองวิธีที่ต่างกัน อดีตที่เรียกว่าอ่านและหลังถูกเรียกว่านักเขียน เรายังไม่ได้สร้างนักเขียนเลยลองทำดู
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"
น่ากลัว ตอนนี้เราสามารถเขียนและอ่านตัวแปรอินสแตนซ์@name
โดยใช้วิธีอ่านและนักเขียน ยกเว้นวิธีนี้ทำบ่อยครั้งทำไมต้องเสียเวลาเขียนวิธีการเหล่านี้ทุกครั้ง เราสามารถทำได้ง่ายขึ้น
class Person
attr_reader :name
attr_writer :name
end
แม้สิ่งนี้จะได้รับซ้ำ ๆ เมื่อคุณต้องการทั้งผู้อ่านและนักเขียนเพียงแค่ใช้ accessor!
class Person
attr_accessor :name
end
person = Person.new
person.name = "Dennis"
person.name # => "Dennis"
ทำงานในลักษณะเดียวกัน! และเดาอะไร: ตัวแปรอินสแตนซ์@name
ในวัตถุบุคคลของเราจะถูกตั้งค่าเช่นเดียวกับเมื่อเราทำด้วยตนเองดังนั้นคุณสามารถใช้มันในวิธีอื่นได้
class Person
attr_accessor :name
def greeting
"Hello #{@name}"
end
end
person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"
แค่นั้นแหละ. เพื่อให้เข้าใจถึงวิธีการattr_reader
, attr_writer
และattr_accessor
วิธีการสร้างจริงวิธีการที่คุณอ่านคำตอบอื่น ๆ , หนังสือ, เอกสารทับทิม
attr_accessor
เป็นวิธีการที่เรียกว่าในชั้นเรียนปัจจุบันและ:name
เป็นพารามิเตอร์ที่คุณส่งผ่านไปยังวิธีการที่ มันไม่ได้เป็นรูปแบบพิเศษมันเป็นวิธีการที่ง่าย ถ้าคุณจะให้มัน@name
ตัวแปรมันจะไม่ทำให้รู้สึกเพราะ @name nil
จะมี attr_accessor nil
ดังนั้นมันจะเป็นเช่นการเขียน คุณไม่ได้ผ่านตัวแปรที่จำเป็นในการสร้างคุณกำลังผ่านชื่อที่คุณต้องการให้ตัวแปรถูกเรียกใช้
name
และตัวแปร@name
ไม่เหมือนกัน อย่าสับสนพวกเขา คุณมีตัวแปรอินสแตนซ์@name
ในชั้นเรียนของคุณและคุณกำหนดattr_reader :name
ให้สามารถอ่านได้จากภายนอก หากattr_reader
ไม่มีวิธีง่ายๆคุณสามารถเข้าถึง@name
นอกห้องเรียนได้
attr_accessorเป็นเพียงวิธีการหนึ่ง (ลิงก์ควรให้ข้อมูลเชิงลึกมากขึ้นเกี่ยวกับวิธีการทำงาน - ดูที่วิธีการสร้างคู่และการสอนควรแสดงวิธีการใช้งาน)
เคล็ดลับคือว่าclass
เป็นไม่ได้เป็นความหมายในรูบี (มันเป็น "เพียงแค่คำนิยาม" ในภาษาเช่น C ++ และ Java) แต่มันเป็นการแสดงออกที่ประเมิน มันเป็นในระหว่างการประเมินผลนี้เมื่อattr_accessor
วิธีการที่ถูกเรียกซึ่งในทางกลับกันแก้ไขชั้นปัจจุบัน - จำผู้รับโดยปริยาย: self.attr_accessor
ซึ่งself
เป็นวัตถุระดับ "เปิด" ที่จุดนี้
ความต้องการattr_accessor
และเพื่อนคือ:
Ruby เช่น Smalltalk ไม่อนุญาตให้เข้าถึงตัวแปรอินสแตนซ์นอกเมธอด 1สำหรับวัตถุนั้น นั่นคือตัวแปรอินสแตนซ์ไม่สามารถเข้าถึงได้ในx.y
รูปแบบตามปกติในการพูด Java หรือแม้กระทั่งงูหลาม ในทับทิมy
จะถูกนำมาใช้เป็นข้อความที่จะส่ง (หรือ "วิธีการโทร") ดังนั้นattr_*
เมธอดจะสร้าง wrappers ที่พร็อกซี@variable
เข้าถึงอินสแตนซ์ผ่านวิธีที่สร้างขึ้นแบบไดนามิก
หม้อไอน้ำครับ
หวังว่านี่จะอธิบายรายละเอียดเล็กน้อยบางอย่าง การเข้ารหัสที่มีความสุข
1สิ่งนี้ไม่เป็นความจริงอย่างเคร่งครัดและมี"เทคนิค" รอบ ๆ สิ่งนี้แต่ไม่มีการสนับสนุนทางไวยากรณ์สำหรับการเข้าถึง "ตัวแปรอินสแตนซ์สาธารณะ"
attr_accessor
คือ (ตามที่ระบุไว้ @pst) เป็นเพียงวิธีการหนึ่ง สิ่งนี้คือการสร้างวิธีการเพิ่มเติมสำหรับคุณ
ดังนั้นรหัสนี้ที่นี่:
class Foo
attr_accessor :bar
end
เทียบเท่ากับรหัสนี้:
class Foo
def bar
@bar
end
def bar=( new_value )
@bar = new_value
end
end
คุณสามารถเขียนวิธีการนี้ด้วยตัวคุณเองใน Ruby:
class Module
def var( method_name )
inst_variable_name = "@#{method_name}".to_sym
define_method method_name do
instance_variable_get inst_variable_name
end
define_method "#{method_name}=" do |new_value|
instance_variable_set inst_variable_name, new_value
end
end
end
class Foo
var :bar
end
f = Foo.new
p f.bar #=> nil
f.bar = 42
p f.bar #=> 42
attr_accessor
และพบได้ที่นี่ในที่สุด! แม้ว่ามันจะแก้ปัญหาของฉันได้ แต่ฉันอยากรู้ว่าฉันสามารถหาตัวอย่างการใช้งานเช่นนี้ได้ที่ไหน
attr_accessor
ง่ายมาก:
attr_accessor :foo
เป็นทางลัดสำหรับ:
def foo=(val)
@foo = val
end
def foo
@foo
end
มันไม่มีอะไรมากไปกว่า getter / setter สำหรับวัตถุ
โดยพื้นฐานแล้วพวกเขาปลอมแอตทริบิวต์ข้อมูลที่สาธารณชนเข้าถึงได้ซึ่ง Ruby ไม่มี
มันเป็นเพียงวิธีการที่กำหนดวิธี getter และ setter สำหรับตัวแปรอินสแตนซ์ ตัวอย่างการใช้งานจะเป็น:
def self.attr_accessor(*names)
names.each do |name|
define_method(name) {instance_variable_get("@#{name}")} # This is the getter
define_method("#{name}=") {|arg| instance_variable_set("@#{name}", arg)} # This is the setter
end
end
คำตอบข้างต้นส่วนใหญ่ใช้รหัส คำอธิบายนี้พยายามที่จะตอบคำถามโดยไม่ใช้คำใด ๆ ผ่านการเปรียบเทียบ / เรื่อง:
บุคคลภายนอกไม่สามารถเข้าถึงความลับของ CIA ภายในได้
ลองจินตนาการถึงสถานที่ลับสุดยอด: ซีไอเอ ไม่มีใครรู้ว่าเกิดอะไรขึ้นใน CIA นอกเหนือจากผู้คนใน CIA กล่าวอีกนัยหนึ่งบุคคลภายนอกไม่สามารถเข้าถึงข้อมูลใด ๆ ใน CIA แต่เนื่องจากมันไม่ดีที่มีองค์กรที่เป็นความลับอย่างสมบูรณ์จึงมีข้อมูลบางอย่างให้กับโลกภายนอก - มีเพียงสิ่งเดียวที่ CIA ต้องการให้ทุกคนรู้แน่นอน: เช่นผู้อำนวยการของ CIA เปรียบเทียบแผนกนี้เป็นมิตรกับสิ่งแวดล้อมอย่างไร หน่วยงานรัฐบาลอื่น ๆ ทั้งหมด ฯลฯ ข้อมูลอื่น ๆ : เช่นใครเป็นหน่วยปฏิบัติการลับในอิรักหรืออัฟกานิสถานสิ่งเหล่านี้อาจเป็นความลับในอีก 150 ปีข้างหน้า
หากคุณอยู่นอก CIA คุณจะสามารถเข้าถึงข้อมูลที่เปิดเผยต่อสาธารณะเท่านั้น หรือเพื่อใช้สำนวน CIA คุณสามารถเข้าถึงข้อมูลที่ "เคลียร์" เท่านั้น
ข้อมูลที่ CIA ต้องการเปิดเผยต่อสาธารณชนทั่วไปภายนอก CIA นั้นเรียกว่า: attribute
ความหมายของคุณสมบัติการอ่านและเขียน:
ในกรณีของ CIA คุณลักษณะส่วนใหญ่คือ "อ่านอย่างเดียว" ซึ่งหมายความว่าหากคุณเป็นบุคคลภายนอกของ CIA คุณสามารถถาม: "ใครเป็นผู้อำนวยการของ CIA" และคุณจะได้รับคำตอบที่ตรง แต่สิ่งที่คุณไม่สามารถทำได้ด้วยคุณลักษณะ "อ่านอย่างเดียว" คือการเปลี่ยนแปลงการเปลี่ยนแปลงใน CIA เช่นคุณไม่สามารถโทรออกได้และตัดสินใจทันทีว่าคุณต้องการให้ Kim Kardashian เป็นผู้อำนวยการหรือคุณต้องการให้ Paris Hilton เป็นผู้บัญชาการทหารสูงสุด
หากแอตทริบิวต์ให้สิทธิ์การเข้าถึง "เขียน" คุณสามารถทำการเปลี่ยนแปลงได้หากคุณต้องการแม้ว่าคุณจะอยู่ภายนอก มิฉะนั้นสิ่งเดียวที่คุณสามารถทำได้คืออ่าน
ในคำอื่น ๆ accessors ช่วยให้คุณสามารถสอบถามหรือทำการเปลี่ยนแปลงกับองค์กรที่ไม่อนุญาตให้บุคคลภายนอกในขึ้นอยู่กับว่า accessors เป็นอ่านหรือเขียน accessors
วัตถุภายในคลาสสามารถเข้าถึงซึ่งกันและกันได้อย่างง่ายดาย
สิ่งเดียวกันกับคลาสและความสามารถของคุณในการเข้าถึงตัวแปรคุณสมบัติและวิธีการต่างๆ HTH! คำถามใด ๆ โปรดถามและฉันหวังว่าฉันสามารถชี้แจง
หากคุณคุ้นเคยกับแนวคิด OOP คุณต้องคุ้นเคยกับวิธี getter และ setter attr_accessor ทำเช่นเดียวกันใน Ruby
ทะเยอทะยานและ Setter ด้วยวิธีทั่วไป
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"
วิธีการตั้งค่า
def name=(val)
@name = val
end
วิธีการทะเยอทะยาน
def name
@name
end
วิธี Getter และ Setter ใน Ruby
class Person
attr_accessor :name
end
person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"
ฉันประสบปัญหานี้เช่นกันและเขียนคำตอบที่ค่อนข้างยาวสำหรับคำถามนี้ มีคำตอบที่ยอดเยี่ยมเกี่ยวกับเรื่องนี้อยู่แล้ว แต่ใครก็ตามที่กำลังมองหาคำอธิบายเพิ่มเติมฉันหวังว่าคำตอบของฉันจะช่วย
เริ่มต้นวิธีการ
เริ่มต้นช่วยให้คุณสามารถตั้งค่าข้อมูลเป็นอินสแตนซ์ของวัตถุเมื่อสร้างอินสแตนซ์แทนที่จะต้องตั้งค่าพวกเขาในบรรทัดแยกในรหัสของคุณทุกครั้งที่คุณสร้างอินสแตนซ์ใหม่ของชั้นเรียน
class Person
def initialize(name)
@name = name
end
def greeting
"Hello #{@name}"
end
end
person = Person.new("Denis")
puts person.greeting
ในรหัสข้างต้นเรากำลังตั้งค่าชื่อ“ เดนิส” โดยใช้วิธีการเตรียมใช้งานโดยส่งเดนนิสผ่านพารามิเตอร์ในการเตรียมใช้งาน หากเราต้องการตั้งชื่อโดยไม่มีวิธีการเริ่มต้นเราสามารถทำเช่นนี้:
class Person
attr_accessor :name
# def initialize(name)
# @name = name
# end
def greeting
"Hello #{name}"
end
end
person = Person.new
person.name = "Dennis"
puts person.greeting
ในโค้ดข้างต้นเราตั้งชื่อโดยเรียกใช้เมธอด attr_accessor setter โดยใช้ person.name แทนที่จะตั้งค่าเมื่อเริ่มต้นวัตถุ
ทั้ง "วิธีการ" ในการทำงานนี้ แต่การเริ่มต้นช่วยเราประหยัดเวลาและบรรทัดของรหัส
นี่เป็นงานเริ่มต้นเท่านั้น คุณไม่สามารถเริ่มต้นเป็นวิธีการได้ ในการรับค่าของออบเจกต์อินสแตนซ์คุณจำเป็นต้องใช้ getters และ setters (attr_reader (get), attr_writer (set) และ attr_accessor (ทั้งคู่) ดูด้านล่างสำหรับรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งเหล่านั้น
Getters, Setters (attr_reader, attr_writer, attr_accessor)
Getters, attr_reader: จุดประสงค์ทั้งหมดของผู้เรียกคือส่งคืนค่าของตัวแปรอินสแตนซ์เฉพาะ เยี่ยมชมตัวอย่างโค้ดด้านล่างเพื่อดูรายละเอียดเกี่ยวกับสิ่งนี้
class Item
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
def item_name
@item_name
end
def quantity
@quantity
end
end
example = Item.new("TV",2)
puts example.item_name
puts example.quantity
ในรหัสข้างต้นคุณกำลังเรียกวิธีการ“ item_name” และ“ ปริมาณ” ในตัวอย่างของรายการ“ ตัวอย่าง” “ ใส่ example.item_name” และ“ example.quantity” จะส่งกลับ (หรือ“ รับ”) ค่าสำหรับพารามิเตอร์ที่ส่งผ่านไปยัง“ ตัวอย่าง” และแสดงไปที่หน้าจอ
โชคดีที่ Ruby มีวิธีการที่ทำให้เราสามารถเขียนโค้ดนี้ได้อย่างกระชับยิ่งขึ้น วิธีการ attr_reader ดูรหัสด้านล่าง;
class Item
attr_reader :item_name, :quantity
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
end
item = Item.new("TV",2)
puts item.item_name
puts item.quantity
ไวยากรณ์นี้ทำงานในลักษณะเดียวกันเท่านั้น แต่จะช่วยเราหกบรรทัดของรหัส ลองนึกภาพถ้าคุณมีสถานะเพิ่มอีก 5 อันเนื่องมาจากคลาสรายการ รหัสจะยาวเร็ว
Setters, attr_writer: สิ่งที่ทำให้ฉันก้าวแรกด้วยวิธี setter คือในสายตาของฉันมันดูเหมือนจะทำหน้าที่เหมือนกันกับวิธีการเริ่มต้น ด้านล่างฉันอธิบายความแตกต่างตามความเข้าใจของฉัน
ตามที่ระบุไว้ก่อนหน้านี้วิธีการเตรียมใช้งานช่วยให้คุณสามารถกำหนดค่าสำหรับอินสแตนซ์ของวัตถุเมื่อสร้างวัตถุ
แต่จะเกิดอะไรขึ้นถ้าคุณต้องการตั้งค่าในภายหลังหลังจากสร้างอินสแตนซ์หรือเปลี่ยนค่าหลังจากที่เริ่มต้นแล้ว นี่จะเป็นสถานการณ์ที่คุณจะใช้เมธอด setter นั่นคือความแตกต่าง คุณไม่จำเป็นต้อง“ ตั้งค่า” สถานะใดสถานะหนึ่งเมื่อคุณใช้เมธอด attr_writer ในตอนแรก
รหัสด้านล่างเป็นตัวอย่างของการใช้เมธอด setter เพื่อประกาศค่า item_name สำหรับอินสแตนซ์ของคลาสรายการ โปรดสังเกตว่าเรายังคงใช้วิธี getter ต่อไปเพื่อ attr_reader เพื่อให้เราสามารถรับค่าและพิมพ์ไปยังหน้าจอในกรณีที่คุณต้องการทดสอบรหัสด้วยตัวคุณเอง
class Item
attr_reader :item_name
def item_name=(str)
@item_name = (str)
end
end
โค้ดด้านล่างเป็นตัวอย่างของการใช้ attr_writer เพื่อย่อรหัสของเราอีกครั้งและประหยัดเวลา
class Item
attr_reader :item_name
attr_writer :item_name
end
item = Item.new
puts item.item_name = "TV"
โค้ดด้านล่างเป็นการทำซ้ำของตัวอย่างการเริ่มต้นด้านบนที่เราใช้ initialize เพื่อตั้งค่าวัตถุของ item_name เมื่อสร้าง
class Item
attr_reader :item_name
def initialize(item_name)
@item_name = item_name
end
end
item = Item.new("TV")
puts item.item_name
attr_accessor: ทำหน้าที่ของทั้ง attr_reader และ attr_writer ช่วยให้คุณประหยัดอีกหนึ่งบรรทัดของรหัส
ฉันคิดว่าส่วนหนึ่งของสิ่งที่สับสน Rubyists / โปรแกรมเมอร์ใหม่ (เหมือนตัวเอง) คือ:
"เหตุใดฉันจึงไม่สามารถบอกได้ว่าอินสแตนซ์นั้นมีแอตทริบิวต์ที่กำหนด (เช่นชื่อ) และให้ค่าคุณลักษณะนั้นทั้งหมดในการโฉบเดียว"
พูดคุยทั่วไปมากกว่านี้เล็กน้อย แต่นี่คือวิธีการคลิกสำหรับฉัน:
ได้รับ:
class Person
end
เราไม่ได้กำหนดบุคคลเป็นสิ่งที่สามารถมีชื่อหรือคุณลักษณะอื่น ๆ
ดังนั้นหากเรา:
baby = Person.new
... และพยายามตั้งชื่อพวกเขา ...
baby.name = "Ruth"
เราได้รับข้อผิดพลาดเพราะใน Rubyland คลาสของวัตถุบุคคลนั้นไม่ใช่สิ่งที่เกี่ยวข้องหรือมี "ชื่อ" ... ยัง!
แต่เราสามารถใช้วิธีการใด ๆ ที่กำหนด (ดูคำตอบก่อนหน้า) เป็นวิธีที่จะพูดว่า "ตัวอย่างของคลาสบุคคล ( baby
) ตอนนี้สามารถมีคุณลักษณะที่เรียกว่า 'ชื่อ' ดังนั้นเราไม่เพียงมีวิธีการรับและ ตั้งชื่อนั้น แต่มันสมเหตุสมผลสำหรับเราที่จะทำเช่นนั้น "
อีกครั้งกดปุ่มคำถามนี้จากมุมที่แตกต่างกันเล็กน้อยและทั่วไปมากขึ้น แต่ฉันหวังว่านี้จะช่วยให้อินสแตนซ์ต่อไปของคนชั้นเรียนที่หาทางไปที่หัวข้อนี้
เพียงแค่ใส่มันจะกำหนดตัวตั้งค่าและทะเยอทะยานสำหรับชั้นเรียน
สังเกตได้ว่า
attr_reader :v is equivalant to
def v
@v
end
attr_writer :v is equivalant to
def v=(value)
@v=value
end
ดังนั้น
attr_accessor :v which means
attr_reader :v; attr_writer :v
เทียบเท่ากับการกำหนด setter และทะเยอทะยานสำหรับชั้นเรียน
เพียงattr-accessor
สร้างgetter
และsetter
วิธีการสำหรับแอตทริบิวต์ที่ระบุ
attr_accessor
วิธีที่จะเข้าใจมันก็คือการคิดออกว่ารหัสข้อผิดพลาดลดโดยมี
ตัวอย่าง:
class BankAccount
def initialize( account_owner )
@owner = account_owner
@balance = 0
end
def deposit( amount )
@balance = @balance + amount
end
def withdraw( amount )
@balance = @balance - amount
end
end
มีวิธีการดังต่อไปนี้:
$ bankie = BankAccout.new("Iggy")
$ bankie
$ bankie.deposit(100)
$ bankie.withdraw(5)
วิธีการต่อไปนี้จะเกิดข้อผิดพลาด:
$ bankie.owner #undefined method `owner'...
$ bankie.balance #undefined method `balance'...
owner
และbalance
ไม่ได้ในทางเทคนิควิธีการแต่แอตทริบิวต์ ระดับ bankaccount ไม่ได้และdef owner
def balance
หากเป็นเช่นนั้นคุณสามารถใช้สองคำสั่งด้านล่าง แต่ทั้งสองวิธีไม่ได้อยู่ที่นั่น อย่างไรก็ตามคุณสามารถเข้าถึงแอททริบิวเสมือนว่าคุณเข้าถึงวิธีผ่านattr_accessor
!! ดังนั้นคำว่า attr_accessor
คุณลักษณะ การเข้าถึง มันเข้าถึงคุณลักษณะเช่นคุณจะเข้าถึงวิธีการ
การเพิ่มattr_accessor :balance, :owner
อนุญาตให้คุณอ่านและเขียนbalance
และowner
"วิธีการ" ตอนนี้คุณสามารถใช้ 2 วิธีล่าสุด
$ bankie.balance
$ bankie.owner
กำหนดแอตทริบิวต์ที่มีชื่อสำหรับโมดูลนี้โดยที่ชื่อคือ symbol.id2name สร้างตัวแปรอินสแตนซ์ (@name) และวิธีการเข้าถึงที่สอดคล้องกันเพื่ออ่าน สร้างเมธอดชื่อ = เพื่อตั้งค่าแอ็ตทริบิวต์
module Mod
attr_accessor(:one, :two)
end
Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]
เพื่อสรุปคุณสมบัติ accessor aka attr_accessor ให้สองวิธีฟรี
เช่นเดียวกับใน Java พวกมันถูกเรียกว่า getters และ setters
คำตอบมากมายแสดงตัวอย่างที่ดีดังนั้นฉันจะสรุป
#the_attribute
และ
# the_attribute =
ในเอกสารทับทิมเก่า hash tag # หมายถึงวิธีการ มันอาจรวมถึงคำนำหน้าชื่อชั้น ... MyClass # my_method
ฉันใหม่กับทับทิมและต้องจัดการกับความเข้าใจเรื่องประหลาดต่อไปนี้ อาจช่วยคนอื่นในอนาคต ในท้ายที่สุดมันเป็นดังกล่าวข้างต้นที่ 2 ฟังก์ชั่น (def myvar, def myvar =) ทั้งสองได้รับโดยปริยายสำหรับการเข้าถึง @ myvar แต่วิธีการเหล่านี้สามารถถูกแทนที่โดยการประกาศในท้องถิ่น
class Foo
attr_accessor 'myvar'
def initialize
@myvar = "A"
myvar = "B"
puts @myvar # A
puts myvar # B - myvar declared above overrides myvar method
end
def test
puts @myvar # A
puts myvar # A - coming from myvar accessor
myvar = "C" # local myvar overrides accessor
puts @myvar # A
puts myvar # C
send "myvar=", "E" # not running "myvar =", but instead calls setter for @myvar
puts @myvar # E
puts myvar # C
end
end
คุณสมบัติเป็นองค์ประกอบระดับที่สามารถเข้าถึงได้จากนอกวัตถุ พวกเขาเป็นที่รู้จักกันว่าคุณสมบัติในภาษาการเขียนโปรแกรมอื่น ๆ อีกมากมาย ค่าของพวกเขาสามารถเข้าถึงได้โดยใช้ "จุดสัญกรณ์" เช่นเดียวกับใน object_name.attribute_name แตกต่างจาก Python และภาษาอื่น ๆ สองสาม Ruby ไม่อนุญาตให้ตัวแปรอินสแตนซ์สามารถเข้าถึงได้โดยตรงจากนอกวัตถุ
class Car
def initialize
@wheels = 4 # This is an instance variable
end
end
c = Car.new
c.wheels # Output: NoMethodError: undefined method `wheels' for #<Car:0x00000000d43500>
ในตัวอย่างข้างต้น c เป็นตัวอย่าง (วัตถุ) ของคลาสรถยนต์ เราพยายามอ่านค่าตัวแปรอินสแตนซ์ของล้อจากนอกวัตถุไม่สำเร็จ สิ่งที่เกิดขึ้นคือทับทิมพยายามเรียกเมธอดชื่อล้อที่อยู่ภายในวัตถุ c แต่ไม่ได้กำหนดวิธีดังกล่าว ในระยะสั้น object_name.attribute_name พยายามเรียกวิธีชื่อ attribute_name ภายในวัตถุ ในการเข้าถึงค่าของตัวแปรล้อจากภายนอกเราจำเป็นต้องใช้เมธอดอินสแตนซ์โดยใช้ชื่อนั้นซึ่งจะส่งคืนค่าของตัวแปรนั้นเมื่อถูกเรียก ที่เรียกว่าวิธีการเข้าถึง ในบริบทการเขียนโปรแกรมทั่วไปวิธีการทั่วไปในการเข้าถึงตัวแปรอินสแตนซ์จากนอกวัตถุคือการใช้วิธีการเข้าถึงที่เรียกว่าวิธี getter และ setter
ในตัวอย่างต่อไปนี้เราได้เพิ่มวิธี getter และ setter ให้กับคลาส Car เพื่อเข้าถึงตัวแปรล้อจากนอกวัตถุ นี่ไม่ใช่ "วิธีการทับทิม" ของการกำหนด getters และ setters; มันทำหน้าที่เพียงเพื่อแสดงให้เห็นว่าสิ่งที่ getter และ setter วิธีการทำ
class Car
def wheels # getter method
@wheels
end
def wheels=(val) # setter method
@wheels = val
end
end
f = Car.new
f.wheels = 4 # The setter method was invoked
f.wheels # The getter method was invoked
# Output: => 4
ตัวอย่างงานด้านบนและรหัสที่คล้ายกันมักใช้ในการสร้างวิธี getter และ setter ในภาษาอื่น อย่างไรก็ตาม Ruby มีวิธีที่ง่ายกว่าในการทำเช่นนี้: สามวิธีในตัวที่เรียกว่า attr_reader, attr_writer และ attr_acessor เมธอด attr_reader ทำให้ตัวแปรอินสแตนซ์สามารถอ่านได้จากภายนอก attr_writer ทำให้สามารถเขียนได้และ attr_acessor ทำให้สามารถอ่านและเขียนได้
ตัวอย่างด้านบนสามารถเขียนใหม่ได้เช่นนี้
class Car
attr_accessor :wheels
end
f = Car.new
f.wheels = 4
f.wheels # Output: => 4
ในตัวอย่างข้างต้นแอ็ตทริบิวต์ Wheels จะสามารถอ่านและเขียนได้จากนอกวัตถุ ถ้าแทนที่จะเป็น attr_accessor เราใช้ attr_reader มันจะเป็นแบบอ่านอย่างเดียว ถ้าเราใช้ attr_writer มันจะเป็นแบบเขียนอย่างเดียว วิธีการทั้งสามนั้นไม่ใช่ getters และ setters ในตัวเอง แต่เมื่อถูกเรียกมันจะสร้าง getter และ setter สำหรับเรา พวกเขาเป็นวิธีการที่สร้างแบบไดนามิก (โดยทางโปรแกรม) สร้างวิธีอื่น ๆ ; ที่เรียกว่า metaprogramming
ตัวอย่างแรก (ยาวกว่า) ซึ่งไม่ใช้วิธีการในตัวของรูบี้ควรใช้เมื่อต้องการรหัสเพิ่มเติมในเมธอด getter และ setter ตัวอย่างเช่นเมธอด setter อาจต้องการตรวจสอบข้อมูลหรือทำการคำนวณบางอย่างก่อนที่จะกำหนดค่าให้กับตัวแปรอินสแตนซ์
เป็นไปได้ที่จะเข้าถึง (อ่านและเขียน) ตัวแปรอินสแตนซ์จากนอกวัตถุโดยใช้วิธีการ built-in instance_variable_get และ instance_variable_set อย่างไรก็ตามนี่เป็นเหตุผลที่ไม่ค่อยสมเหตุสมผลและมักเป็นความคิดที่ไม่ดีเนื่องจากการผ่านการห่อหุ้มมีแนวโน้มที่จะทำให้เกิดความเสียหายทุกประเภท
อืมม คำตอบที่ดีมากมาย นี่คือไม่กี่เซ็นต์ของฉันกับมัน
attr_accessor
เป็นวิธีง่าย ๆ ที่ช่วยเราในการทำความสะอาด ( DRY-ing ) ถึงวิธีการทำซ้ำgetter and setter
เพื่อให้เราสามารถมุ่งเน้นไปที่การเขียนตรรกะทางธุรกิจมากขึ้นและไม่ต้องกังวลกับ setters และ getters
หน้าที่หลักของattr_accessorเหนือสิ่งอื่นคือความสามารถในการเข้าถึงข้อมูลจากไฟล์อื่น ๆ
ดังนั้นคุณมักจะมี attr_reader หรือ attr_writer แต่ข่าวดีก็คือว่า Ruby ช่วยให้คุณรวมสองสิ่งนี้เข้าด้วยกันกับ attr_accessor ฉันคิดว่ามันเป็นวิธีการของฉันไปเพราะมันโค้งมนมากขึ้นหรือหลากหลาย อย่าลืมว่าใน Rails นี่ถูกกำจัดไปแล้วเพราะมันทำเพื่อคุณในด้านหลัง ดังนั้นในคำอื่น ๆ : คุณควรใช้ attr_acitor มากกว่าอีกสองคนเพราะคุณไม่ต้องกังวลกับการเป็นคนเฉพาะเจาะจง accessor ครอบคลุมทุกอย่าง ฉันรู้ว่านี่เป็นคำอธิบายทั่วไปมากกว่า แต่มันช่วยฉันในฐานะมือใหม่
หวังว่านี่จะช่วยได้!