Как избежать создания объекта с таким же атрибутом - PullRequest
0 голосов
/ 03 февраля 2019

У меня есть

class Node
  attr_accessor :name

  def initialize(name)
    @name = name
  end
end

node1 = Node.new(1)
node2 = Node.new(1)

Как лучше всего проверить, существует ли уже узел с таким именем, и избежать создания node2?

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Если вы ожидаете исключение при вызове метода :: new с повторяющимся аргументом, посмотрите ответ @ maxpleaner .
Но если вам нужна ссылка на объектчто вы создали ранее с этим аргументом, используйте другой способ:

class Name
  @@names = {}

  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def self.new(name)
    @@names[name] || @@names[name] = super
  end
end

Теперь вы можете проверить это:

n1 = Name.new(1)
n2 = Name.new(2)
n2a = Name.new(2)
puts n1.object_id, n2.object_id, n2a.object_id
puts n2 == n2a

В моем случае это печатает:

5296300
5264360
5264360
true
0 голосов
/ 03 февраля 2019

Вы должны реализовать это самостоятельно.Это не такая распространенная потребность, поэтому не является встроенным способом сделать это.

Один из способов - использовать Set следующим образом:

require 'set'

class Name
  NAMES = Set.new

  def initialize(name)
    if self.class::NAMES.member?(name)
      raise("already used this value") 
    else
      @name = name
      self.class::NAMES.add(name)
    end
  end
end

Вы также можете использовать массив с include?но производительность хуже.

Также обратите внимание, что вам нужно использовать raise - нет другого способа «отменить» инициализацию объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...