रूबी में attr_accessor क्या है?


1023

मुझे रूबी को समझने attr_accessorमें कठिन समय आ रहा है । क्या कोई मुझे ये समझा सकता है?



1
क्या Attr_accessor Git में इसी तरह काम करता है? मुझे पता है कि कुछ ट्यूटोरियल पर्याप्त व्याख्या नहीं करते हैं और अन्य पूर्व ज्ञान ग्रहण करते हैं।
अंगफिरनज़े डे

10
@Angelfirenze gitसे कोई लेना-देना नहीं है attr_accessor। गिट एक संस्करण नियंत्रण सॉफ्टवेयर है, जबकि रूबी मेंattr_accessor एक विधि है
उज्बेकन

जवाबों:


2359

मान लीजिए कि आपके पास एक वर्ग है 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

यहां तक ​​कि इससे पुनरावृत्ति भी हो सकती है। जब आप पाठक और लेखक दोनों चाहते हैं तो बस एक्सेसर का उपयोग करें!

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विधियाँ वास्तव में आपके लिए विधियाँ उत्पन्न करती हैं, अन्य उत्तर, किताबें, रूबी डॉक्स पढ़ें।


46
@ शकुनिन - उस स्पष्ट उत्तर के लिए धन्यवाद। मेरे लिए क्या याद आ रही है कि रूबी सिंटैक्स एक कॉलन का सुझाव क्यों देता है: 'उदाहरण के लिए attr_ * कथन में चर? ऐसा लगता है कि यह उसी '@' सिंटैक्स का उपयोग करने के लिए अधिक सीधे होगा जो चर का उल्लेख करने के लिए कक्षा में कहीं और उपयोग किया जाता है।
विल

207
@WilliamSmith आपके प्रश्न का उत्तर देने के लिए आपको यह समझने की आवश्यकता है कि attr_accessorवर्तमान कक्षा में कहा जाने वाला एक तरीका है, और :nameएक पैरामीटर है जिसे आप उस विधि से पास करते हैं। यह एक विशेष वाक्यविन्यास नहीं है, यह एक सरल विधि है। यदि आप इसे @nameपरिवर्तनशील देना चाहते हैं, तो इसका कोई मतलब नहीं होगा, क्योंकि @name में शामिल होगा nil। तो यह लिखने जैसा होगा attr_accessor nil। आप इसे एक चर नहीं दे रहे हैं जिसे इसे बनाने की आवश्यकता है, आप उस नाम को पारित कर रहे हैं जिसे आप चाहते हैं कि चर कहा जाए।
मैक्स चेर्नाक

23
@ ठाकुनिन - यह कुल समझ में आता है। मैंने आज ही सीखा है कि माणिक वास्तव में 'चल रहा है' क्योंकि यह एक फ़ाइल के माध्यम से पार्स करता है और यह कि प्रत्येक कथन और अभिव्यक्ति वास्तव में किसी वस्तु पर एक विधि कॉल है। सहित attr_accessor। बहुत मददगार।
विल

52
3 साल तक रेल का उपयोग किया, यह भी कभी नहीं पता था। शर्म
शीन जिआओ

5
@ बूमिंडा हां, लेकिन विधि nameऔर चर @nameएक ही चीज नहीं हैं। उन्हें भ्रमित मत करो। आपके पास @nameअपनी कक्षा में उदाहरण चर है, और आप attr_reader :nameइसे बाहर से पढ़ने में सक्षम होने के लिए परिभाषित करते हैं। इसके बिना attr_readerकोई सरल तरीका नहीं है जिससे आप @nameअपनी कक्षा के बाहर पहुँच सकते हैं ।
मैक्स चारणक

127

attr_accessor है सिर्फ एक विधि । (लिंक यह कैसे काम करता है के साथ अधिक अंतर्दृष्टि प्रदान करना चाहिए - उत्पन्न विधियों के जोड़े को देखो, और एक ट्यूटोरियल आपको यह दिखाना चाहिए कि इसका उपयोग कैसे करना है।)

चाल यह है कि classहै एक परिभाषा नहीं रूबी में (यह "सिर्फ एक परिभाषा" सी ++ और जावा जैसी भाषाओं में), लेकिन यह एक है कि मूल्यांकन करता है अभिव्यक्ति । यह इस मूल्यांकन के दौरान है जब attr_accessorविधि को लागू किया जाता है जो बदले में वर्तमान वर्ग को संशोधित करता है - निहित रिसीवर को याद रखें: self.attr_accessorजहां selfइस बिंदु पर "खुला" वर्ग ऑब्जेक्ट है।

attr_accessorऔर दोस्तों की आवश्यकता है:

  1. रूबी, स्मॉलटाक की तरह, उदाहरण के चर को उस वस्तु के लिए विधियों 1 के बाहर तक पहुँचने की अनुमति नहीं देता है । उदाहरण के लिए, उदाहरण के चर को उस x.yरूप में एक्सेस नहीं किया जा सकता जैसा कि जावा, या पायथन में भी सामान्य है। रूबी yमें हमेशा एक संदेश भेजने के लिए (या "कॉल करने की विधि") के रूप में लिया जाता है। इस प्रकार attr_*विधियाँ ऐसे रैपर बनाती हैं जो @variableडायनेमिक रूप से निर्मित विधियों के माध्यम से आवृत्ति तक पहुँच प्राप्त करते हैं।

  2. बॉयलरप्लेट बेकार है

आशा है कि यह कुछ छोटे विवरणों को स्पष्ट करता है। खुश कोडिंग।


1 यह कड़ाई से सच नहीं है और इसके आस-पास कुछ "तकनीकें" हैं , लेकिन "सार्वजनिक उदाहरण चर" एक्सेस के लिए कोई सिंटैक्स समर्थन नहीं है।


जब आप कहते हैं कि attr_accessor "बस एक विधि है" मैं इसे प्राप्त करता हूं। लेकिन उस पद्धति को कॉल करने के लिए प्रयुक्त वाक्यविन्यास क्या है ? मुझे रूबी प्रलेखन में अनुभाग खोजने में परेशानी हो रही है जो कुछ_मिथोड जैसे सिंटैक्स के बारे में बात करता है: नाम => "जो कुछ भी": नोटेरनाम,: आदि
बीटी

68

attr_accessorएक विधि के रूप में (@pst कहा गया है) है। यह क्या करता है आप के लिए और अधिक तरीकों का निर्माण।

तो यह कोड यहाँ है:

class Foo
  attr_accessor :bar
end

इस कोड के बराबर है:

class Foo
  def bar
    @bar
  end
  def bar=( new_value )
    @bar = new_value
  end
end

आप रूबी में स्वयं इस प्रकार की विधि लिख सकते हैं:

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

3
यह एक महान उदाहरण है जहां मेटाप्रोग्रामिंग का उपयोग यहां तक ​​कि सबसे शुरुआती स्तर के परिदृश्यों में भी किया जाता है। बहुत अच्छा।
जॉन साइमन

2
मैं एक कार्यान्वयन स्केच की तलाश कर रहा था attr_accessorऔर अंत में यहां पाया गया! हालांकि इससे मेरी समस्या हल हो गई, लेकिन मैं यह जानने के लिए उत्सुक हूं कि (पुस्तक / आधिकारिक डॉक्टर) मैं इस तरह का कार्यान्वयन उदाहरण कहां पा सकता हूं?
वासिफ हुसैन

40

attr_accessor बहुत सरल है:

attr_accessor :foo

इसके लिए एक शॉर्टकट है:

def foo=(val)
  @foo = val
end

def foo
  @foo
end

यह किसी वस्तु के लिए एक गेटटर / सेटर से ज्यादा कुछ नहीं है


10
आपका जवाब ठीक है। 'शोर्टकट' का अर्थ "मेरे शब्द के अनुसार" एक छोटा वैकल्पिक मार्ग है, न कि "सिंटेक्स शुगर" या "इंटरप्रिटेटर द्वारा व्याख्या की गई मैक्रो"।
बोर्सर्सनियर

25

मूल रूप से वे सार्वजनिक रूप से सुलभ डेटा विशेषताओं को नकली करते हैं, जो रूबी के पास नहीं है।


4
हालांकि यह टिप्पणी पूरी तरह से उपयोगी नहीं है, यह सच है। इस तथ्य पर प्रकाश डाला गया कि सार्वजनिक डेटा विशेषताएँ रूबी में "प्राप्त" विधियों के बाहर मौजूद नहीं हैं, जो भाषा सीखने की कोशिश करने वाले किसी व्यक्ति के लिए वास्तव में उपयोगी जानकारी है।
एरिक डैंड

3
यह वास्तव में नीचा नहीं होना चाहिए। एक गैर-रूबी आदमी के रूप में इस सामान का पता लगाने की कोशिश कर रहा है, यह उत्तर बहुत मददगार है!
ब्रैड

1
सहमत, सी # के नाम {पाने के लिए बहुत अनुकरणीय लगता है; सेट;}
डेविड मिलर

17

यह सिर्फ एक विधि है जो उदाहरण चर के लिए गेट्टर और सेटर विधियों को परिभाषित करता है। एक उदाहरण कार्यान्वयन होगा:

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

इस तरह से कई विशेषताओं को संभालना बहुत अच्छा है!
वासिफ हुसैन

यह एक अन्य प्रश्न को हल करने के लिए एक बहुत ही उपयोगी कोड स्निपेट था जिसे मैंने मेटाप्रोग्रामिंग से संबंधित किया था।
अलेक्सवेंटुरायो

15

बिना किसी कोड के सरल व्याख्या

अधिकांश उपरोक्त उत्तर कोड का उपयोग करते हैं। यह स्पष्टीकरण किसी सादृश्य / कहानी के माध्यम से बिना किसी का उपयोग किए इसका उत्तर देने का प्रयास करता है:

बाहरी पक्ष आंतरिक CIA रहस्यों का उपयोग नहीं कर सकते

  • आइए एक बहुत ही गुप्त स्थान की कल्पना करें: CIA। किसी को नहीं पता कि सीआईए के अंदर के लोगों के अलावा सीआईए में क्या हो रहा है। दूसरे शब्दों में, बाहरी लोग सीआईए में किसी भी जानकारी का उपयोग नहीं कर सकते हैं। लेकिन क्योंकि यह कोई अच्छा संगठन नहीं है जो पूरी तरह से गुप्त है, कुछ जानकारी बाहर की दुनिया को उपलब्ध कराई जाती है - केवल ऐसी चीजें जो CIA चाहती है कि हर कोई निश्चित रूप से इसके बारे में जानें: उदाहरण के लिए CIA के निदेशक, इस विभाग की तुलना में पर्यावरण के अनुकूल कैसे हैं अन्य सभी सरकारी विभागों आदि के लिए। अन्य जानकारी: जैसे कि इराक या अफगानिस्तान में इसके गुप्त संचालक कौन हैं - इस प्रकार की चीजें संभवतः अगले 150 वर्षों तक एक रहस्य बनी रहेंगी।

  • यदि आप सीआईए के बाहर हैं तो आप केवल उस जानकारी तक पहुंच सकते हैं, जिसे उसने जनता के लिए उपलब्ध कराया है। या सीआईए पार्लेंस का उपयोग करने के लिए आप केवल "क्लीयर" की गई जानकारी तक पहुंच सकते हैं।

  • सीआईए के बाहर आम जनता के लिए सीआईए जो जानकारी उपलब्ध कराना चाहता है, उसे कहा जाता है: विशेषताएँ।

विशेषताओं को पढ़ने और लिखने का अर्थ:

  • CIA के मामले में, अधिकांश विशेषताएँ "केवल पढ़ने के लिए" हैं। इसका मतलब है कि यदि आप सीआईए के लिए बाहरी पार्टी हैं , तो आप पूछ सकते हैं: "सीआईए का निदेशक कौन है?" और आपको सीधा जवाब मिलेगा। लेकिन आप "केवल पढ़ने के लिए" विशेषताओं के साथ क्या नहीं कर सकते हैं , सीआईए में परिवर्तन करना है। उदाहरण के लिए आप फोन कॉल नहीं कर सकते हैं और अचानक तय करते हैं कि आप चाहते हैं कि किम कार्दशियन निर्देशक हों, या आप चाहते हैं कि पेरिस हिल्टन इन चीफ कमांडर बनें।

  • यदि विशेषताओं ने आपको "लिखना" पहुंच दी है, तो आप चाहें तो बदलाव कर सकते हैं, भले ही आप बाहर थे। अन्यथा, केवल एक चीज जो आप कर सकते हैं वह है।

    दूसरे शब्दों में, एक्सेसर्स आपको पूछताछ करने, या उन संगठनों में बदलाव करने की अनुमति देते हैं जो अन्यथा बाहरी लोगों को अंदर नहीं जाने देते हैं, इस पर निर्भर करता है कि एक्सेसर्स पढ़े गए हैं या एक्सेसर्स लिखते हैं।

एक वर्ग के अंदर की वस्तुएँ आसानी से एक दूसरे तक पहुँच सकती हैं

  • दूसरी ओर, यदि आप पहले से ही सीआईए के अंदर थे , तो आप आसानी से काबुल में अपने सीआईए को ऑपरेटिव कह सकते हैं क्योंकि यह जानकारी आसानी से सुलभ है, क्योंकि आप पहले से ही अंदर हैं। लेकिन यदि आप सीआईए के बाहर हैं , तो आपको बस एक्सेस नहीं दी जाएगी: आप यह नहीं जान पाएंगे कि वे कौन हैं (एक्सेस पढ़ें), और आप अपने मिशन को नहीं बदल पाएंगे (एक्सेस एक्सेस लिख सकते हैं)।

कक्षाओं और अपने भीतर चर, संपत्तियों और तरीकों तक पहुंचने की क्षमता के साथ एक ही चीज का सटीक निष्पादन करें। HTH! कोई प्रश्न, कृपया पूछें और मुझे आशा है कि मैं स्पष्ट कर सकता हूं।


आपका स्पष्टीकरण समझ में आता है! ? +1 क्षमा करें, इसका अभिव्यक्ति "जानकारी जो सीआईए द्वारा मंजूरी दे दी है सही यकीन है
Kouty

CIA में विभिन्न "क्लीयरेंस" स्तर हैं: उदाहरण के लिए टॉप सीक्रेट (कोई नहीं, लेकिन प्रेज़) या पब्लिक ट्रस्ट (हर कोई इस जानकारी को पढ़ सकता है)। CIA वास्तव में बहुत ही शांत तथ्य प्रदान करता है!
BKSpurgeon

आप केवल कार्दशियन, पेरिस हिल्टन उदाहरणों के लिए उत्थान के लायक हैं :) मुझे लगा कि यह राष्ट्रपति के लिए ट्रम्प के साथ काफी बुरा था, उन दो प्रभारी ओम की कल्पना करें!
rmcsharry

हाँ! यह है कि हम क्या जरूरत है, कोड के बिना StackOverflow! :-)
मार्विन

13

यदि आप OOP अवधारणा से परिचित हैं, तो आपको गेट्टर और सेटर विधि से परिचित होना चाहिए। attr_accessor रूबी में यही करता है।

सामान्य तरीके से गेटटर और सेटर

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

रूबी में गेट्टर और सेटर विधि

class Person
  attr_accessor :name
end

person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"

2
सही स्पष्टीकरण! यह एक बहुत ही आसान व्यवहार है और इसे बहुत आसानी से ओवरराइड किया जा सकता है।
रुबाइडर

12

मैंने इस समस्या का सामना किया और इस सवाल का कुछ लंबा जवाब लिखा। इस पर पहले से ही कुछ शानदार जवाब हैं, लेकिन किसी को भी अधिक स्पष्टीकरण की तलाश है, मुझे उम्मीद है कि मेरा जवाब मदद कर सकता है

प्रारंभिक विधि

प्रारंभ में आपको प्रत्येक बार जब आप कक्षा का एक नया उदाहरण बनाते हैं तो कोड में एक अलग लाइन पर उन्हें सेट करने के बजाय उदाहरण के निर्माण पर किसी ऑब्जेक्ट के इंस्टेंस पर डेटा सेट करने की अनुमति देता है।

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

उपरोक्त कोड में, हम ऑब्जेक्ट के आरंभीकरण पर मूल्यों को सेट करने के बजाय person.name का उपयोग करके attr_accessor सेटर विधि पर कॉल करके नाम सेट करते हैं।

इस काम को करने के दोनों "तरीके", लेकिन इनिशियलाइज़ हमें समय और कोड की लाइनों को बचाता है।

यह इनिशियलाइज़ का एकमात्र काम है। आप एक विधि के रूप में इनिशियलाइज़ नहीं कर सकते। वास्तव में एक उदाहरण ऑब्जेक्ट के मूल्यों को प्राप्त करने के लिए आपको गेटर्स और सेटर (attr_reader (get), attr_writer (सेट), और attr_accessor (दोनों)) का उपयोग करने की आवश्यकता होती है। उन पर अधिक विस्तार के लिए नीचे देखें।

गेटर्स, सेटर्स (attr_reader, attr_writer, attr_accessor)

गेटर्स, एट्र्रैडर: एक गेटर का पूरा उद्देश्य किसी विशेष उदाहरण चर के मान को वापस करना है। इस पर ब्रेकडाउन के लिए नीचे दिए गए सैंपल कोड पर जाएँ।

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

ऊपर दिए गए कोड में आप आइटम "उदाहरण" के उदाहरण पर "आइटम_नाम" और "मात्रा" कह रहे हैं। "Example.item_name" और "example.quantity" वापस आ जाएगी (या "प्राप्त करें") उन मापदंडों के लिए मान जो "उदाहरण" में पारित किए गए थे और उन्हें स्क्रीन पर प्रदर्शित करते हैं।

सौभाग्य से रूबी में एक अंतर्निहित विधि है जो हमें इस कोड को अधिक संक्षेप में लिखने की अनुमति देती है; 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 और राज्य थे? कोड बहुत जल्दी मिल जाएगा।

सेटर्स, एट्री_राइटर: सेटर विधियों के साथ पहली बार में जो मुझे पार कर गया, वह यह है कि मेरी नजर में यह इनिशियलाइज़ मेथड को एक समान कार्य करता प्रतीत हो रहा था। नीचे मैं अपनी समझ के आधार पर अंतर समझाता हूं;

जैसा कि पहले कहा गया है, इनिशियलाइज़ विधि आपको ऑब्जेक्ट निर्माण पर ऑब्जेक्ट की आवृत्ति के लिए मान सेट करने की अनुमति देता है।

लेकिन क्या होगा अगर आप उदाहरणों को बाद में स्थापित करना चाहते थे, उदाहरण के लिए, या उन्हें शुरू करने के बाद उन्हें बदल दें? यह एक ऐसा परिदृश्य होगा जहां आप एक सेटर विधि का उपयोग करेंगे। यह ज्ञान है। जब आप प्रारंभ में attr_writer पद्धति का उपयोग कर रहे हों, तो आपको किसी विशेष स्थिति को "सेट" करने की आवश्यकता नहीं है।

नीचे दिया गया कोड आइटम वर्ग के इस उदाहरण के लिए value_name को घोषित करने के लिए एक सेटर विधि का उपयोग करने का एक उदाहरण है। ध्यान दें कि हम गेट्टर विधि का उपयोग करना जारी रखते हैं ताकि हम मान प्राप्त कर सकें और उन्हें स्क्रीन पर प्रिंट कर सकें, बस अगर आप अपने दम पर कोड का परीक्षण करना चाहते हैं।

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"

नीचे दिया गया कोड ऊपर के इनिशियलाइज़ उदाहरण का एक पुनरीक्षण है, जहाँ हम इनिशियलाइज़ का उपयोग कर रहे हैं सृजन पर 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 दोनों के कार्यों को करता है, जिससे आपको कोड की एक और लाइन की बचत होती है।


10

मुझे लगता है कि नए रूबिस्ट / प्रोग्रामर (जैसे खुद) क्या भ्रमित हैं:

"मैं सिर्फ यह उदाहरण क्यों नहीं बता सकता कि इसमें कोई विशेषता है (उदाहरण के लिए, नाम) और उस विशेषता को एक झपट्टा में सभी मान दें?"

थोड़ा और सामान्यीकृत, लेकिन यह इस तरह से मेरे लिए क्लिक किया है:

दिया हुआ:

class Person
end

हमने व्यक्ति को किसी ऐसी चीज़ के रूप में परिभाषित नहीं किया है जिसका नाम या उस मामले के लिए कोई अन्य विशेषता हो सकती है।

तो अगर हम:

baby = Person.new

... और उन्हें एक नाम देने की कोशिश ...

baby.name = "Ruth"

हमें एक त्रुटि मिलती है, क्योंकि रूबीलैंड में, वस्तु का एक व्यक्ति वर्ग ऐसा कुछ नहीं है जो "नाम" ... के साथ जुड़ा या सक्षम है!

लेकिन हम दिए गए तरीकों में से किसी का भी उपयोग कर सकते हैं (पिछले उत्तरों को देखें) कहने के तरीके के रूप में, "एक व्यक्ति वर्ग ( baby) का एक उदाहरण अब 'नाम' नामक एक विशेषता हो सकता है , इसलिए हमारे पास न केवल प्राप्त करने का एक वाक्यात्मक तरीका है और उस नाम को सेट करना, लेकिन यह हमारे लिए ऐसा करने के लिए समझ में आता है। ”

फिर, इस सवाल को थोड़ा अलग और अधिक सामान्य कोण से मारते हुए, लेकिन मुझे उम्मीद है कि इससे क्लास पर्सन के अगले उदाहरण को मदद मिलती है जो इस धागे के लिए अपना रास्ता खोज लेते हैं।


7

सीधे शब्दों में कहें तो यह कक्षा के लिए एक सेटर और गेट्टर को परिभाषित करेगा।

ध्यान दें कि

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 

वर्ग के लिए एक सेटर और गेट्टर को परिभाषित करने के लिए समतुल्य हैं।


5

बस निर्दिष्ट विशेषताओं के लिए और तरीके attr-accessorबनाता हैgettersetter


5

इसे समझने का एक और तरीका यह है कि यह होने से कौन सा त्रुटि कोड समाप्त हो जाता है 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

2

इस मॉड्यूल के लिए एक नामित विशेषता को परिभाषित करता है, जहां नाम है symbol.id2name, एक उदाहरण चर (@name) और इसे पढ़ने के लिए एक संबंधित एक्सेस विधि बना रहा है। विशेषता सेट करने के लिए = नाम की एक विधि भी बनाता है।

module Mod
  attr_accessor(:one, :two)
end
Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]

1

एक विशेषता एक्सेसर उर्फ ​​अट्रैक्टर को संक्षिप्त करने के लिए आपको दो फ्री मेथड देता है।

जैसे जावा में उन्हें गेटर्स और सेटर कहा जाता है।

कई जवाबों ने अच्छे उदाहरण दिखाए हैं इसलिए मैं बस संक्षिप्त ही होने जा रहा हूं।

#the_attribute

तथा

# The_attribute =

पुराने रूबी डॉक्स में हैश टैग # एक विधि का अर्थ है। इसमें एक वर्ग नाम उपसर्ग भी शामिल हो सकता है ... MyClass # my_method


1

मैं माणिक के लिए नया हूं और निम्नलिखित विचित्रता को समझने के लिए बस सौदा करना था। भविष्य में किसी और की मदद कर सकते हैं। अंत में जैसा कि ऊपर उल्लेख किया गया है, जहां 2 कार्य (डीवर 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

0

विशेषताएँ और पहुँच विधि

विशेषताएँ वर्ग घटक हैं जिन्हें ऑब्जेक्ट के बाहर से एक्सेस किया जा सकता है। उन्हें कई अन्य प्रोग्रामिंग भाषाओं में गुणों के रूप में जाना जाता है। उनके मान "डॉट संकेतन" का उपयोग करके सुलभ हैं, जैसा कि object_name.attribute_name में है। पाइथन और कुछ अन्य भाषाओं के विपरीत, रूबी वस्तु के बाहर से सीधे उदाहरण चर को एक्सेस करने की अनुमति नहीं देती है।

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 कार वर्ग का एक उदाहरण (ऑब्जेक्ट) है। हमने ऑब्जेक्ट के बाहर से पहियों के उदाहरण चर के मूल्य को पढ़ने का असफल प्रयास किया। क्या हुआ कि रूबी ने सी ऑब्जेक्ट के भीतर पहियों नामक एक विधि को कॉल करने का प्रयास किया, लेकिन ऐसी कोई विधि परिभाषित नहीं की गई। संक्षेप में, object_name.attribute_name किसी ऑब्जेक्ट के भीतर Method_name नामक विधि को कॉल करने का प्रयास करता है। बाहर से चर चर के मूल्य का उपयोग करने के लिए, हमें उस नाम से एक इंस्टेंस विधि को लागू करने की आवश्यकता है, जो उस चर के मूल्य को वापस बुलाया जाएगा। इसे एक्सेसर विधि कहा जाता है। सामान्य प्रोग्रामिंग संदर्भ में, ऑब्जेक्ट के बाहर से एक इंस्टेंस वेरिएबल को एक्सेस करने का सामान्य तरीका एक्सेसर विधियों को लागू करना है, जिसे गेट्टर और सेटर विधियों के रूप में भी जाना जाता है।

निम्नलिखित उदाहरण में, हमने ऑब्जेक्ट के बाहर से पहियों के चर को एक्सेस करने के लिए कार क्लास में गेट्टर और सेटर के तरीकों को जोड़ा है। यह गेटर्स और सेटर्स को परिभाषित करने का "रूबी तरीका" नहीं है; यह केवल यह बताने के लिए कार्य करता है कि गेट्टर और सेटर विधियां क्या करती हैं।

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

उपरोक्त उदाहरण काम करता है और समान कोड का उपयोग आमतौर पर अन्य भाषाओं में गेट्टर और सेटर विधियों को बनाने के लिए किया जाता है। हालांकि, रूबी ऐसा करने के लिए एक सरल तरीका प्रदान करती है: तीन अंतर्निर्मित विधियाँ जिन्हें अट्रर्रीडर, अट्रर_राइटर और अट्रर_एकेसर कहा जाता है। Attr_reader विधि बाहर से पठनीय एक परिवर्तनशील चर बनाता है, attr_writer इसे लेखन योग्य बनाता है, और attr_acistr इसे पठनीय और लेखन योग्य बनाता है।

उपरोक्त उदाहरण को इस तरह से फिर से लिखा जा सकता है।

class Car
  attr_accessor :wheels
end

f = Car.new
f.wheels = 4
f.wheels  # Output: => 4

उपरोक्त उदाहरण में, पहियों की विशेषता ऑब्जेक्ट के बाहर से पठनीय और लिखने योग्य होगी। यदि attr_accessor के बजाय, हमने attr_reader का उपयोग किया, तो यह केवल पढ़ने के लिए होगा। यदि हम attr_writer का उपयोग करते हैं, तो यह केवल लेखन होगा। वे तीन विधियां स्वयं में गेटर्स और सेटर नहीं हैं, लेकिन जब बुलाया जाता है, तो वे हमारे लिए गेट्टर और सेटर विधियां बनाते हैं। वे विधियां हैं जो गतिशील रूप से (प्रोग्रामेटिक रूप से) अन्य विधियां उत्पन्न करती हैं; जिसे मेटाप्रोग्रामिंग कहा जाता है।

पहला (लंबा) उदाहरण, जो रूबी की अंतर्निहित विधियों को नियोजित नहीं करता है, इसका उपयोग केवल तब किया जाना चाहिए जब गेट्टर और सेटर विधियों में अतिरिक्त कोड आवश्यक हो। उदाहरण के लिए, एक सेटर विधि को उदाहरण वेरिएबल के लिए मान निर्दिष्ट करने से पहले डेटा को मान्य करने या कुछ गणना करने की आवश्यकता हो सकती है।

इंस्टेंस_वर्जेबल_गेट और इंस्टेंस_वर्जेबल_सेट बिल्ट-इन तरीकों का उपयोग करके ऑब्जेक्ट के बाहर से (पढ़ें और लिखें) इंस्टेंस वेरिएबल तक पहुंचना संभव है। हालांकि, यह शायद ही कभी उचित है और आमतौर पर एक बुरा विचार है, क्योंकि इनकैप्सुलेशन को दरकिनार करके सभी प्रकार के कहर को मिटाया जाता है।


-2

हममम। बहुत अच्छे जवाब। यहाँ उस पर मेरा कुछ सेंट है।

  • attr_accessorएक सरल विधि (सफाई में मदद करता है सूखी-इंग ) ऊपर दोहराgetter and setter तरीकों।

  • ताकि हम व्यावसायिक तर्क लिखने पर अधिक ध्यान केंद्रित कर सकें और बसने वालों और पाने वालों की चिंता न कर सकें।


-3

अन्य लोगों पर attr_accessor की मुख्य कार्यक्षमता अन्य फ़ाइलों से डेटा तक पहुँचने की क्षमता है।
तो आप आमतौर पर attr_reader या attr_writer होगा, लेकिन अच्छी खबर यह है कि Ruby आपको attr_accessor के साथ इन दोनों को एक साथ संयोजित करने देता है। मैं इसके बारे में सोचता हूं कि यह मेरी विधि है क्योंकि यह अधिक अच्छी तरह से गोल या बहुमुखी है। इसके अलावा, ध्यान रखें कि रेल में, यह समाप्त हो जाता है क्योंकि यह बैक एंड में आपके लिए करता है। तो दूसरे शब्दों में: आप अन्य दो पर attr_acurer का उपयोग करने से बेहतर हैं क्योंकि आपको विशिष्ट होने के बारे में चिंता करने की ज़रूरत नहीं है, एक्सेसर इसे कवर करता है। मुझे पता है कि यह एक सामान्य स्पष्टीकरण से अधिक है लेकिन इसने मुझे एक शुरुआत के रूप में मदद की।

उम्मीद है कि इस मदद की!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.