रूबी में एनम कैसे लागू करें?


323

रूबी में एनम मुहावर को लागू करने का सबसे अच्छा तरीका क्या है? मैं एक ऐसी चीज की तलाश कर रहा हूं जिसका उपयोग मैं (लगभग) जावा / सी # एनम की तरह कर सकता हूं।


7
@auramo, अच्छा सवाल, और सबसे अच्छा जवाब के लिए बढ़िया विकल्प। इसे प्यार करें या नफरत करें, आपको कोई टाइप-सेफ्टी नहीं मिलती और (कम से कम रूबी में) कोई टाइपो-सेफ्टी नहीं। जब मैं सी # में और बाद में जावा में एक एनम की खोज कर रहा था, तो मैं रोमांचित था।
दान रोसेनस्टार्क

2
इस सवाल के साथ समस्या यह है कि जावा और सी # एनम नाटकीय रूप से अलग चीजें हैं। एक जावा एनम सदस्य एक वस्तु उदाहरण और एक सिंगलटन है। एक जावा एनम में एक कंस्ट्रक्टर हो सकता है। इसके विपरीत, C # enums आदिम मूल्यों से दूर हैं। प्रश्नकर्ता को किस व्यवहार की तलाश है? हालांकि यह संभावना है कि C # केस वांछित है, C या C ++ की बजाय जावा का स्पष्ट रूप से उल्लेख किया गया है, इसलिए कुछ संदेह है। यह सुझाव देने के लिए कि रूबी में 'सुरक्षित' होने का कोई तरीका नहीं है, यह पारदर्शी रूप से गलत है, लेकिन आपको कुछ अधिक परिष्कृत लागू करना होगा।
user1164178

जवाबों:


317

दो तरीके। प्रतीक ( :fooसंकेतन) या स्थिरांक ( FOOसंकेतन)।

जब आप शाब्दिक तार के साथ कोडिंग के बिना पठनीयता को बढ़ाना चाहते हैं तो प्रतीक उपयुक्त हैं।

postal_code[:minnesota] = "MN"
postal_code[:new_york] = "NY"

जब आपके पास एक अंतर्निहित मूल्य है जो महत्वपूर्ण है, तो कॉन्स्टेंट उपयुक्त हैं। बस अपने स्थिरांक को रखने के लिए एक मॉड्यूल घोषित करें और उसके बाद स्थिरांक घोषित करें।

module Foo
  BAR = 1
  BAZ = 2
  BIZ = 4
end

flags = Foo::BAR | Foo::BAZ # flags = 3

2
क्या होगा यदि इन एनम को भी डेटाबेस में संग्रहीत किया जाए? क्या प्रतीक संकेतन काम करेगा? मुझे संदेह है ...
n

यदि मैं किसी डेटाबेस में बचत कर रहा हूं तो मैं स्थिरांक दृष्टिकोण का उपयोग करूंगा। बेशक तब आपको किसी प्रकार के लुकअप को करना होगा जब डेटा को डीबी से वापस खींच लिया जाए। :minnesota.to_sप्रतीक के स्ट्रिंग संस्करण को बचाने के लिए डेटाबेस में सहेजते समय आप कुछ का उपयोग भी कर सकते हैं । रेल, मेरा मानना ​​है कि इसमें से कुछ से निपटने के लिए कुछ सहायक तरीके हैं।
मलाईबाई

7
क्या एक मॉड्यूल समूह स्थिरांक के लिए बेहतर नहीं होगा - जैसा कि आप इसका कोई उदाहरण नहीं बनाने जा रहे हैं?
थोमथोम

3
बस एक टिप्पणी। रूबी नामकरण सम्मेलनों के बारे में थोड़ा दर्द है लेकिन वास्तव में उनके बारे में स्पष्ट नहीं है जब तक आप उन पर यात्रा नहीं करते हैं। Enums के नाम सभी कैप होने चाहिए और माड्यूल नाम के पहले अक्षर को रूबी के लिए कैपिटल किया जाना चाहिए ताकि पता चल सके कि मॉड्यूल स्थिरांक का मॉड्यूल है।
रोकुजोलडी

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

59

मुझे आश्चर्य है कि किसी ने निम्नलिखित की तरह कुछ की पेशकश नहीं की है ( आरएपीआई मणि से काटा गया ):

class Enum

  private

  def self.enum_attr(name, num)
    name = name.to_s

    define_method(name + '?') do
      @attrs & num != 0
    end

    define_method(name + '=') do |set|
      if set
        @attrs |= num
      else
        @attrs &= ~num
      end
    end
  end

  public

  def initialize(attrs = 0)
    @attrs = attrs
  end

  def to_i
    @attrs
  end
end

जिसका उपयोग इस तरह किया जा सकता है:

class FileAttributes < Enum
  enum_attr :readonly,       0x0001
  enum_attr :hidden,         0x0002
  enum_attr :system,         0x0004
  enum_attr :directory,      0x0010
  enum_attr :archive,        0x0020
  enum_attr :in_rom,         0x0040
  enum_attr :normal,         0x0080
  enum_attr :temporary,      0x0100
  enum_attr :sparse,         0x0200
  enum_attr :reparse_point,  0x0400
  enum_attr :compressed,     0x0800
  enum_attr :rom_module,     0x2000
end

उदाहरण:

>> example = FileAttributes.new(3)
=> #<FileAttributes:0x629d90 @attrs=3>
>> example.readonly?
=> true
>> example.hidden?
=> true
>> example.system?
=> false
>> example.system = true
=> true
>> example.system?
=> true
>> example.to_i
=> 7

यह डेटाबेस परिदृश्यों में अच्छी तरह से खेलता है, या जब सी स्टाइल स्थिरांक / एनमों के साथ काम करता है (जैसा कि एफएफआई का उपयोग करते समय होता है , जिसे आरएपीआई व्यापक उपयोग करता है)।

इसके अलावा, आपको टाइपो के बारे में चिंता करने की ज़रूरत नहीं है, क्योंकि आप हैश-टाइप समाधान का उपयोग कर सकते हैं।


1
यह उस विशेष समस्या को हल करने का एक शानदार तरीका है, लेकिन जिस कारण से किसी ने भी यह सुझाव नहीं दिया है कि शायद यह इस तथ्य के साथ है कि यह सी # / जावा एनम की तरह नहीं है।
mlibby

1
यह थोड़ा अधूरा है, लेकिन एक अच्छे दृष्टिकोण के रूप में कार्य करता है कि आप एक गतिशील दृष्टिकोण के साथ समाधान कैसे लागू कर सकते हैं। यह FlagsAttribute सेट के साथ C # enum में कुछ समानता के साथ है, लेकिन ऊपर दिए गए प्रतीक / निरंतर आधारित समाधानों की तरह, यह कई लोगों में से एक है। समस्या मूल प्रश्न है, जो अपने इरादे में गड़बड़ है (C # और जावा विनिमेय नहीं है)। रूबी में वस्तुओं को आइटम करने के कई तरीके हैं; सही का चयन करना समस्या के हल होने पर निर्भर करता है। धीरे-धीरे प्रतिकृति सुविधाओं की आपको आवश्यकता नहीं है, गुमराह है। सही उत्तर को संदर्भ पर निर्भर होना पड़ता है।
user1164178

52

ऐसा करने का सबसे मुहावरेदार तरीका प्रतीकों का उपयोग करना है। उदाहरण के लिए, इसके बजाय:

enum {
  FOO,
  BAR,
  BAZ
}

myFunc(FOO);

... आप सिर्फ प्रतीकों का उपयोग कर सकते हैं:

# You don't actually need to declare these, of course--this is
# just to show you what symbols look like.
:foo
:bar
:baz

my_func(:foo)

यह एनम की तुलना में थोड़ा अधिक खुला है, लेकिन यह रूबी भावना के साथ अच्छी तरह से फिट बैठता है।

प्रतीक भी बहुत अच्छा प्रदर्शन करते हैं। समानता के लिए दो प्रतीकों की तुलना, उदाहरण के लिए, दो तार की तुलना में बहुत तेज है।


107
तो रूबी आत्मा है: "
टाइपोस

82
लोकप्रिय रूबी फ्रेमवर्क रनटाइम मेटाप्रोग्रामिंग पर बहुत अधिक निर्भर करते हैं, और बहुत अधिक लोड-टाइम जाँच करने से रूबी की अधिकांश अभिव्यंजक शक्ति दूर हो जाएगी। समस्याओं से बचने के लिए, अधिकांश रूबी प्रोग्रामर परीक्षण-संचालित डिज़ाइन का अभ्यास करते हैं, जो न केवल टाइपो बल्कि तर्क त्रुटियों को भी ढूंढेगा।
एमके

10
@ अय्यर: वैसे, भाषा का डिज़ाइन ट्रेडऑफ़्स की एक श्रृंखला है, और भाषा की विशेषताएं बातचीत करती हैं। यदि आप एक अच्छी, उच्च-गतिशील भाषा चाहते हैं, तो रूबी के साथ जाएं, अपनी यूनिट के परीक्षण पहले लिखें, और भाषा की भावना के साथ जाएं। :-) यदि वह नहीं है जो आप ढूंढ रहे हैं, तो दर्जनों उत्कृष्ट भाषाएं हैं, जिनमें से प्रत्येक अलग-अलग ट्रेडऑफ़ बनाती है।
17

10
@ नीम, मैं सहमत हूं, लेकिन मेरा व्यक्तिगत मुद्दा यह है कि मैं रूबी में काफी सहज महसूस करता हूं, लेकिन मैं रूबी में सहज रिफैक्टरिंग महसूस नहीं करता हूं। और अब जब मैंने इकाई परीक्षण लिखना शुरू कर दिया है (अंत में), मुझे पता है कि वे रामबाण नहीं हैं: मेरा अनुमान 1 है) कि रूबी कोड को बड़े पैमाने पर फिर से प्राप्त नहीं किया जाता है, अक्सर अभ्यास में और 2) रूबी अंत नहीं है -ऑन-द-लाइन गतिशील भाषाओं के संदर्भ में, ठीक है क्योंकि यह स्वचालित रूप से रिफ्लेक्टर के लिए कठिन है। मेरा प्रश्न २३१ my५ got ९ देखें, जो कि, छोटे लोगों द्वारा, अजीब तरीके से लिया गया था।
दान रोसेनस्टार्क

4
हाँ, लेकिन उन तारों का उपयोग करना सी # भाषा की भावना में नहीं होगा, यह केवल एक बुरा अभ्यास है।
एड एस।

38

मैं निम्नलिखित दृष्टिकोण का उपयोग करता हूं:

class MyClass
  MY_ENUM = [MY_VALUE_1 = 'value1', MY_VALUE_2 = 'value2']
end

मुझे यह निम्नलिखित फायदों के लिए पसंद है:

  1. यह एक पूरे के रूप में दृष्टिगत मूल्यों का समूह बनाता है
  2. यह कुछ संकलन-समय की जाँच करता है (केवल प्रतीकों का उपयोग करने के विपरीत)
  3. मैं आसानी से सभी संभावित मूल्यों की सूची का उपयोग कर सकता हूं: बस MY_ENUM
  4. मैं आसानी से अलग-अलग मूल्यों तक पहुँच सकता हूँ: MY_VALUE_1
  5. इसमें सिंबल ही नहीं, किसी भी प्रकार के मूल्य हो सकते हैं

प्रतीक बेहतर कारण हो सकते हैं कि आपको बाहरी वर्ग का नाम नहीं लिखना है, यदि आप इसे किसी अन्य कक्षा में उपयोग कर रहे हैं ( MyClass::MY_VALUE_1)


4
मुझे लगता है कि यह सबसे अच्छा जवाब है। कार्यक्षमता, वाक्यविन्यास और न्यूनतम कोड ओवरहेड जावा / सी # के सबसे करीब आते हैं। इसके अलावा, आप परिभाषाओं को एक स्तर से भी अधिक गहरा कर सकते हैं और फिर भी MyClass :: MY_ENUM.flatten के साथ सभी मानों को पुनर्प्राप्त कर सकते हैं। एक साइड नोट के रूप में मैं यहां बड़े नामों का उपयोग करूंगा जैसा कि रूबी में स्थिरांक के लिए मानक है। MyClass :: MyEnum एक उपवर्ग के संदर्भ के लिए गलत हो सकता है।
Janosch

@ जेनोसच, मैंने नाम अपडेट कर दिए हैं। सुझाव के लिए धन्यवाद
एलेक्सी

मैं अभी भी थोड़ा भ्रमित हूं, और लिंक 410'd (नहीं, 404 नहीं)। क्या आप उदाहरण दे सकते हैं कि इस एनम का उपयोग कैसे किया जाएगा?
शेल्वैकु

17

यदि आप रेल्स 4.2 या अधिक का उपयोग कर रहे हैं तो आप रेल एनम का उपयोग कर सकते हैं।

रेल में अब किसी भी रत्न को शामिल किए बिना डिफ़ॉल्ट रूप से दुश्मनी है।

यह जावा, C ++ एनम के समान (और सुविधाओं के साथ अधिक) समान है।

Http://edgeapi.rubyonrails.org/classes/ActiveRecord/Emum.html से उद्धृत :

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end

# conversation.update! status: 0
conversation.active!
conversation.active? # => true
conversation.status  # => "active"

# conversation.update! status: 1
conversation.archived!
conversation.archived? # => true
conversation.status    # => "archived"

# conversation.update! status: 1
conversation.status = "archived"

# conversation.update! status: nil
conversation.status = nil
conversation.status.nil? # => true
conversation.status      # => nil

7
जैसा कि आपने कहा - यदि ओपी रेल का उपयोग नहीं कर रहा है (या अधिक सटीक रूप से ऑब्जेक्ट ActiveRecord का नहीं है) उपयोगी नहीं है। बस मेरे पतन को समझा रहा है सब।
गेर

2
ये रूबी में नहीं हैं, यह आपके डेटाबेस में Enums के लिए एक ActiveRecord इंटरफ़ेस है। नहीं एक सामान्य उपाय जो किसी अन्य उपयोग-मामले में लागू किया जा सकता है।
एडम लाससेक

मैंने अपने उत्तर में इसका उल्लेख किया है।
वेदांत

यह रेल का उपयोग करते हुए IFF का सबसे अच्छा जवाब है।
TheUtherSide

मुझे यह पसंद नहीं है क्योंकि इसे रेल डेटाबेस (काम करने के लिए) में संग्रहित किया जाना चाहिए और क्योंकि यह Conversationकक्षा के कई उदाहरणों को बनाने की अनुमति देता है - मेरा मानना ​​है कि इसे केवल 1 उदाहरण की अनुमति देनी चाहिए।
प्रोग्रेसिल्स

8

यह रूबी में दुश्मनी के लिए मेरा दृष्टिकोण है। मैं छोटे और मीठे के लिए जा रहा था, जरूरी नहीं कि सबसे सी-लाइक हो। कोई विचार?

module Kernel
  def enum(values)
    Module.new do |mod|
      values.each_with_index{ |v,i| mod.const_set(v.to_s.capitalize, 2**i) }

      def mod.inspect
        "#{self.name} {#{self.constants.join(', ')}}"
      end
    end
  end
end

States = enum %w(Draft Published Trashed)
=> States {Draft, Published, Trashed} 

States::Draft
=> 1

States::Published
=> 2

States::Trashed
=> 4

States::Draft | States::Trashed
=> 3


8

शायद सबसे अच्छा हल्के दृष्टिकोण होगा

module MyConstants
  ABC = Class.new
  DEF = Class.new
  GHI = Class.new
end

इस तरह मानों के संबद्ध नाम हैं, जैसा कि जावा / सी # में:

MyConstants::ABC
=> MyConstants::ABC

सभी मान प्राप्त करने के लिए, आप कर सकते हैं

MyConstants.constants
=> [:ABC, :DEF, :GHI] 

यदि आप एक एनुम का क्रमिक मूल्य चाहते हैं, तो आप कर सकते हैं

MyConstants.constants.index :GHI
=> 2

1
IMHO यह बहुत बारीकी से जावा से उपयोग और उद्देश्य (प्रकार की सुरक्षा) की नकल करता है, साथ ही, प्राथमिकता के मामले के रूप में, स्थिरांक को इस तरह परिभाषित किया जा सकता है:class ABC; end
wik

8

मुझे पता है कि इस सवाल को पोस्ट किए हुए एक लंबा समय हो गया है, लेकिन मेरे पास एक ही सवाल था और इस पोस्ट ने मुझे जवाब नहीं दिया। मैं यह देखने के लिए एक आसान तरीका चाहता था कि संख्या क्या दर्शाती है, आसान तुलना है, और एनम का प्रतिनिधित्व करने वाले कॉलम का उपयोग करके लुकअप के लिए सभी ActiveRecord समर्थन का समर्थन करता है।

मुझे कुछ भी नहीं मिला, इसलिए मैंने यिनम नामक एक भयानक कार्यान्वयन किया, जिसमें मुझे वह सब कुछ मिल गया जिसकी मुझे तलाश थी। ऐनक के टन, तो मुझे यकीन है कि यह सुरक्षित है।

कुछ उदाहरण विशेषताएं:

COLORS = Enum.new(:COLORS, :red => 1, :green => 2, :blue => 3)
=> COLORS(:red => 1, :green => 2, :blue => 3)
COLORS.red == 1 && COLORS.red == :red
=> true

class Car < ActiveRecord::Base    
  attr_enum :color, :COLORS, :red => 1, :black => 2
end
car = Car.new
car.color = :red / "red" / 1 / "1"
car.color
=> Car::COLORS.red
car.color.black?
=> false
Car.red.to_sql
=> "SELECT `cars`.* FROM `cars` WHERE `cars`.`color` = 1"
Car.last.red?
=> true

5

यदि आप प्रतीकों के साथ टाइपोस के बारे में चिंतित हैं, तो सुनिश्चित करें कि जब आप किसी गैर-मौजूद कुंजी के साथ एक मूल्य का उपयोग करते हैं तो आपका कोड एक अपवाद उठाता है। आप इसके fetchबजाय इसका उपयोग करके कर सकते हैं []:

my_value = my_hash.fetch(:key)

या यदि आप एक गैर-मौजूद कुंजी की आपूर्ति करते हैं, तो डिफ़ॉल्ट रूप से एक अपवाद बढ़ाएँ:

my_hash = Hash.new do |hash, key|
  raise "You tried to access using #{key.inspect} when the only keys we have are #{hash.keys.inspect}"
end

यदि हैश पहले से मौजूद है, तो आप अपवाद-बढ़ाने वाले व्यवहार को जोड़ सकते हैं:

my_hash = Hash[[[1,2]]]
my_hash.default_proc = proc do |hash, key|
  raise "You tried to access using #{key.inspect} when the only keys we have are #{hash.keys.inspect}"
end

आम तौर पर, आपको स्थिरांक के साथ टाइपो सुरक्षा के बारे में चिंता करने की ज़रूरत नहीं है। यदि आप एक स्थिर नाम को मिस करते हैं, तो यह आमतौर पर एक अपवाद बढ़ाएगा।


ऐसा लगता है कि आप स्पष्ट रूप से कहे बिना, हैश के साथ दुश्मनी की वकालत कर रहे हैं । ऐसा कहने के लिए अपने उत्तर को संपादित करना एक अच्छा विचार हो सकता है। : (मैं भी वर्तमान में रूबी में enums की तरह कुछ के लिए एक की जरूरत है, और यह हल करने के लिए मेरा पहला दृष्टिकोण हैश का उपयोग करना है FOO_VALUES = {missing: 0, something: 1, something_else: 2, ...}यह परिभाषित करता है कुंजी प्रतीकों। missing, something, आदि, और भी उन्हें जुड़े मूल्यों के माध्यम से तुलनीय बनाता है।)
तीमू लीस्टी

मेरा मतलब है, बिना उत्तर के बहुत शुरुआत में।
तैमू लीस्टी

4

किसी ने आगे बढ़कर, रेणु नामक एक माणिक रत्न लिखा । यह व्यवहार की तरह निकटतम जावा / सी # प्राप्त करने का दावा करता है। व्यक्तिगत रूप से मैं अभी भी रूबी सीख रहा हूं, और जब मैं एक विशिष्ट वर्ग को स्थिर एनम, संभवत: एक हैश बनाना चाहता था, तो मैं थोड़ा चौंक गया था, यह बिल्कुल Google के माध्यम से आसानी से नहीं मिला था।


रूबी में मुझे कभी एनम की जरूरत नहीं पड़ी। प्रतीक और स्थिरांक मुहावरेदार हैं और समान समस्याओं को हल करते हैं, है न?
चक

शायद चक; लेकिन माणिक में एक एनम के लिए गुगली करना आपको वह दूर नहीं मिलेगा। यह आपको एक सीधे समकक्ष पर लोगों के सर्वोत्तम प्रयास के लिए परिणाम दिखाएगा। जो मुझे आश्चर्यचकित करता है, शायद एक साथ लिपटे हुए अवधारणा के बारे में कुछ अच्छा है।
dlamblin

@ चक प्रतीकों और स्थिरांकों को लागू नहीं किया जाता है, उदाहरण के लिए, मान को छोटे मानों में से एक होना चाहिए।
डेविड मोल्स

3

यह सब निर्भर करता है कि आप जावा या सी # एनम का उपयोग कैसे करते हैं। आप इसे कैसे उपयोग करते हैं यह आप रूबी में चुने गए समाधान को निर्धारित करेंगे।

Setउदाहरण के लिए, मूल प्रकार आज़माएँ :

>> enum = Set['a', 'b', 'c']
=> #<Set: {"a", "b", "c"}>
>> enum.member? "b"
=> true
>> enum.member? "d"
=> false
>> enum.add? "b"
=> nil
>> enum.add? "d"
=> #<Set: {"a", "b", "c", "d"}>

9
प्रतीकों का उपयोग क्यों नहीं करते Set[:a, :b, :c]?
डैन रोसेनस्टार्क

2
यहां प्रतीकों का उपयोग करने के लिए बहुत बेहतर अभ्यास, आईएमओ।
कॉलिन ग्रेव्स

3

हाल ही में हमने एक रत्न जारी किया जो रूबी में एनम को लागू करता है । मेरी पोस्ट में आपको अपने सवालों के जवाब मिलेंगे। इसके अलावा मैंने वहां बताया कि हमारा कार्यान्वयन मौजूदा लोगों की तुलना में बेहतर क्यों है (वास्तव में रूबी में इस सुविधा के कई कार्यान्वयन अभी भी रत्नों के रूप में हैं)।


यह स्पष्ट रूप से बताते हुए बिना आत्म वृद्धि मूल्यों की अनुमति देता है। +1
डिमिड

3

एक अन्य समाधान OpenStruct का उपयोग कर रहा है। अपने सुंदर सीधे आगे और साफ।

https://ruby-doc.org/stdlib-2.3.1/libdoc/ostruct/rdoc/OpenStruct.html

उदाहरण:

# bar.rb
require 'ostruct' # not needed when using Rails

# by patching Array you have a simple way of creating a ENUM-style
class Array
   def to_enum(base=0)
      OpenStruct.new(map.with_index(base).to_h)
   end
end

class Bar

    MY_ENUM = OpenStruct.new(ONE: 1, TWO: 2, THREE: 3)
    MY_ENUM2 = %w[ONE TWO THREE].to_enum

    def use_enum (value)
        case value
        when MY_ENUM.ONE
            puts "Hello, this is ENUM 1"
        when MY_ENUM.TWO
            puts "Hello, this is ENUM 2"
        when MY_ENUM.THREE
            puts "Hello, this is ENUM 3"
        else
            puts "#{value} not found in ENUM"
        end
    end

end

# usage
foo = Bar.new    
foo.use_enum 1
foo.use_enum 2
foo.use_enum 9


# put this code in a file 'bar.rb', start IRB and type: load 'bar.rb'

2

प्रतीक माणिक्य मार्ग है। हालांकि, कभी-कभी किसी को कुछ सी कोड या कुछ या जावा से बात करने की ज़रूरत होती है जो विभिन्न चीजों के लिए कुछ एनम को उजागर करता है।


#server_roles.rb
module EnumLike

  def EnumLike.server_role
    server_Symb=[ :SERVER_CLOUD, :SERVER_DESKTOP, :SERVER_WORKSTATION]
    server_Enum=Hash.new
    i=0
    server_Symb.each{ |e| server_Enum[e]=i; i +=1}
    return server_Symb,server_Enum
  end

end

यह तो इस तरह इस्तेमाल किया जा सकता है


require 'server_roles'

sSymb, sEnum =EnumLike.server_role()

foreignvec[sEnum[:SERVER_WORKSTATION]]=8

यह निश्चित रूप से अमूर्त बनाया जा सकता है और आप हमारे अपने एनम वर्ग को रोल कर सकते हैं


क्या आप server_Symbकिसी विशेष कारण के लिए दूसरे शब्द को चर (जैसे ) में बड़ा कर रहे हैं ? जब तक कोई विशेष कारण नहीं है, यह चर के लिए मुहावरेदार है snake_case_with_all_lower_case, और प्रतीकों के लिए है :lower_case
एंड्रयू ग्रिम

1
@Andrew; यह उदाहरण एक वास्तविक दुनिया की चीज़ से लिया गया था और नेटवर्क प्रोटोकॉल प्रलेखन में xxx_Yyy का उपयोग किया गया था, इसलिए कई भाषाओं में कोड ने एक ही अवधारणा का उपयोग किया ताकि कोई विनिर्देश के परिवर्तनों का पालन कर सके।
जोन्के

1
कोड गोल्फ: server_Symb.each_with_index { |e,i| server_Enum[e] = i}। की कोई जरूरत नहीं i = 0
एंड्रयू ग्रिम

2

मैंने उस तरह से एनम लागू किया है

module EnumType

  def self.find_by_id id
    if id.instance_of? String
      id = id.to_i
    end 
    values.each do |type|
      if id == type.id
        return type
      end
    end
    nil
  end

  def self.values
    [@ENUM_1, @ENUM_2] 
  end

  class Enum
    attr_reader :id, :label

    def initialize id, label
      @id = id
      @label = label
    end
  end

  @ENUM_1 = Enum.new(1, "first")
  @ENUM_2 = Enum.new(2, "second")

end

फिर ऑपरेशन करना आसान है

EnumType.ENUM_1.label

...

enum = EnumType.find_by_id 1

...

valueArray = EnumType.values

2

यह थोड़ा अतिश्योक्तिपूर्ण लगता है, लेकिन यह एक ऐसी पद्धति है जिसका मैंने कुछ बार उपयोग किया है, विशेष रूप से जहां मैं xml या कुछ इस तरह के साथ एकीकरण कर रहा हूं।

#model
class Profession
  def self.pro_enum
    {:BAKER => 0, 
     :MANAGER => 1, 
     :FIREMAN => 2, 
     :DEV => 3, 
     :VAL => ["BAKER", "MANAGER", "FIREMAN", "DEV"]
    }
  end
end

Profession.pro_enum[:DEV]      #=>3
Profession.pro_enum[:VAL][1]   #=>MANAGER

यह मुझे एसी # एनम की कठोरता देता है और यह मॉडल से बंधा हुआ है।


मैं इस दृष्टिकोण की सलाह नहीं दूंगा क्योंकि यह आप पर निर्भर करता है कि आप मैन्युअल रूप से मान सेट करें और यह सुनिश्चित करें कि आपको ऑर्डर सही मिले :VAL। एक सरणी से शुरू करना और हैश का निर्माण करना बेहतर होगा.map.with_index
डेवमॉन्गोस

1
सटीक बिंदु अपने आप को एक ऐसे मूल्य से बांध रहा है जो तीसरे पक्ष द्वारा तय किया गया है। यह प्रति से एक्स्टेंसिबिलिटी के बारे में नहीं है, लेकिन आपके प्रक्रिया सीमाओं के भीतर कम्प्यूटेबिलिटी को प्रभावित करने वाले बाहरी बाधाओं से निपटने के बारे में है।
जजक

निष्पक्ष बिंदु! उस मामले में यह निश्चित रूप से मान निर्दिष्ट करने समझ में आता है, लेकिन मैं के साथ रिवर्स लुकअप करने के लिए इच्छुक होगी .keyया .invertबल्कि एक से :VALकुंजी ( stackoverflow.com/a/10989394/2208016 )
DaveMongoose

हाँ, यह (आप पर वापस) एक उचित बिंदु है। मेरा माणिक असभ्य और निरंकुश था। डीईएफ़ का प्रयोग करेंगे keyयाinvert
JJK

1

अधिकांश लोग प्रतीकों का उपयोग करते हैं (यह :foo_barवाक्यविन्यास है)। वे अद्वितीय अपारदर्शी मूल्यों की तरह हैं। प्रतीक किसी भी एनुम-शैली के प्रकार के नहीं होते हैं, इसलिए वे वास्तव में सी के एनम प्रकार का एक वफादार प्रतिनिधित्व नहीं करते हैं, लेकिन यह बहुत अच्छा है जितना इसे मिलता है।


1
irb(main):016:0> num=[1,2,3,4]
irb(main):017:0> alph=['a','b','c','d']
irb(main):018:0> l_enum=alph.to_enum
irb(main):019:0> s_enum=num.to_enum
irb(main):020:0> loop do
irb(main):021:1* puts "#{s_enum.next} - #{l_enum.next}"
irb(main):022:1> end

आउटपुट:

1 - एक
2 - बी
3 - सी
4 - डी


to_enumआप एक enumera देता टो , जबकि enumमें सी # / जावा भावना एक enumera है tion
DaveMongoose

1
module Status
  BAD  = 13
  GOOD = 24

  def self.to_str(status)
    for sym in self.constants
      if self.const_get(sym) == status
        return sym.to_s
      end
    end
  end

end


mystatus = Status::GOOD

puts Status::to_str(mystatus)

आउटपुट:

GOOD

1

कभी-कभी मुझे बस इतना करना चाहिए कि एनम के मूल्य को प्राप्त करने और जावा दुनिया के समान इसके नाम की पहचान करने में सक्षम होना चाहिए।

module Enum
     def get_value(str)
       const_get(str)
     end
     def get_name(sym)
       sym.to_s.upcase
     end
 end

 class Fruits
   include Enum
   APPLE = "Delicious"
   MANGO = "Sweet"
 end

 Fruits.get_value('APPLE') #'Delicious'
 Fruits.get_value('MANGO') # 'Sweet'

 Fruits.get_name(:apple) # 'APPLE'
 Fruits.get_name(:mango) # 'MANGO'

यह मुझे एनम के उद्देश्य को पूरा करता है और इसे बहुत अधिक विस्तार से रखता है। आप एनम वर्ग के लिए और अधिक विधियाँ जोड़ सकते हैं और वायोला उन्हें सभी परिभाषित एनमों में मुफ्त में प्राप्त कर सकते हैं। उदाहरण के लिए। get_all_names और सामान की तरह।


0

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


0

मुझे लगता है कि एन्यूमरेशन को लागू करने का सबसे अच्छा तरीका प्रतीकों के साथ है क्योंकि बहुत अधिक पूर्णांक के रूप में व्यवहार करता है (जब यह प्रदर्शन की बात आती है, तो object_id का उपयोग तुलना करने के लिए किया जाता है); आपको अनुक्रमण के बारे में चिंता करने की आवश्यकता नहीं है और वे आपके कोड xD में वास्तव में साफ दिखते हैं


0

लगातार समानता से निपटने के लिए एक दुश्मनी की नकल करने का दूसरा तरीका (बेशर्मी से डेव थॉमस से अपनाया गया)। खुले एनमों (प्रतीकों की तरह) और बंद (पूर्वनिर्धारित) एनमों की अनुमति देता है।

class Enum
  def self.new(values = nil)
    enum = Class.new do
      unless values
        def self.const_missing(name)
          const_set(name, new(name))
        end
      end

      def initialize(name)
        @enum_name = name
      end

      def to_s
        "#{self.class}::#@enum_name"
      end
    end

    if values
      enum.instance_eval do
        values.each { |e| const_set(e, enum.new(e)) }
      end
    end

    enum
  end
end

Genre = Enum.new %w(Gothic Metal) # creates closed enum
Architecture = Enum.new           # creates open enum

Genre::Gothic == Genre::Gothic        # => true
Genre::Gothic != Architecture::Gothic # => true

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