Ruby: как узнать, является ли объект одиночным - PullRequest
0 голосов
/ 17 ноября 2018

Документ Ruby docs для Object # singleton_class :

Возвращает класс синглтона obj .Этот метод создает новый одноэлементный класс, если obj не имеет такового.

Следовательно, (несмотря на некоторые комментарии) у объекта не всегда есть синглтонучебный класс.Далее я называю объект синглтоном , если этот объект имеет одноэлементный класс.

Вновь созданный объект не имеет одноэлементного класса и, следовательно, не является одноэлементным:

a = "string"                     # => "string"          # not (yet) a singleton
b = String.new("another one")    # => "another one"     # not (yet) a singleton
[a.class, b.class]               # => [String, String]

Объект становится одноэлементным только после определения одноэлементного метода,

def a.greet
  "hello"
end

или после создания одноэлементного класса из-за определения переменной класса для одноэлементного класса объекта

class << b
  @var = 42
end

К сожалению, в Ruby вызов метода class не показывает, является ли объект одноэлементным, потому что для синглетонов метод не возвращает фактический (singleton) класс, нокласс, используемый для создания объекта:

[a.class, b.class]  # => [String, String]

Просто вызов Marshal.dump раскрывает, является ли объект на самом деле одиночным:

Marshal.dump(a, $stdout)
# TypeError: singleton can't be dumped

Marshal.dump(b, $stdout)
# TypeError: singleton can't be dumped

Есть лилюбой другой, более изящный способ узнать, является ли объект одиночным?

1 Ответ

0 голосов
/ 18 ноября 2018

Я обновляю этот ответ после некоторых дополнительных исследований. Спасибо Амадану за его проницательный ответ на мой связанный вопрос .

Вы можете использовать два одноэлементных метода, чтобы определить, содержит ли объект "существенный" одноэлементный объект, который предотвратил бы его маршалинг.

a = "string-a"
b = "string-b"
c = "string-c"

def a.greet
  "hello"
end

class << b
  @var = 42
end

def no_substantial_singleton?(obj)
  obj.singleton_class.instance_methods(false).empty? &&
  obj.singleton_class.instance_variables.empty?
end

def marshal_if_possible(obj)
    puts Marshal.dump(obj) if no_substantial_singleton?(obj)
end

marshal_if_possible(a) #=>
marshal_if_possible(b) #=>
marshal_if_possible(c) #=> 'string-c:ET'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...