2
class Event

    @event_list = {}

    attr_reader :name, :value

    def initialize(name, value)
      @name  = name
      @value = value
    end

    def to_s
      "#{@value}"
    end

    class << self

      def event_list
          @event_list
      end

      def event_list=(value); end

      def register_event(name, value)
          @event_list[name] = Event.new(name, value)
      end

      def registered_events
          event_list
      end
    end
end

上記のコード スニペットでは、Event.event_list を使用して @event_list にアクセスできます。興味深いのは、この変数を外部から変更できることです。

Event.event_list[:name] = "hello"
Event.event_list  # => { :name => 'hello' }

どうすればこれを回避できますか? @event_list を外部から変更したくありません。

4

4 に答える 4

1

私の知る限り、外部コードが Ruby のインスタンス変数を変更するのを止めることはできません。使用しなくても、 を使用attr_readerattr_writerてアクセスできますObject#instance_variable_set。Ruby にはプライベート変数 (または定数) はありません。変更しないように丁重に依頼された変数だけです。

を定義しない場合、それはプライベート変数でevent_list=あることを示していると見なされます。@event_listこれが問題の解決策です。

次に、可変オブジェクトの問題があります。悲しいことに、Ruby のほとんどすべてのオブジェクトは変更可能であるため、通常、オブジェクトへの参照を取得できれば、それを変更できます。

Object#freezeこれは、オブジェクトが変更されないようにすることで解決できます。残念ながら、これはあなたでさえそれを変更できないことを意味します。

Ruby は物事をロックするのにはあまり適していません。この開放性は言語の中核部分であり、おそらく使用するために学ぶ必要があります。

于 2015-04-22T18:06:12.540 に答える
0

def event_list変数へのアクセスを提供するシングルトンで定義しています。そのメソッドを非公開にする

編集:

宣言するときは@event_list、シングルトン メソッドにスコープがあります。

class Event
  @event_list = {}

  class << self
    def event_list
      # scoped from above
      @event_list
    end
  end
end

Event.event_list #=> {}

アクセスを削除するには、メソッドを非公開にするだけです。

class Event
  @event_list = {}

  class << self
    private

    def event_list
      # scoped from above
      @event_list
    end
  end
end

Event.event_list #=> NoMethodError: private method `event_list' called for Event:Class
于 2015-04-22T17:56:56.977 に答える