Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
哪些Ruby类支持.clone?_Ruby_Clone - Fatal编程技术网

哪些Ruby类支持.clone?

哪些Ruby类支持.clone?,ruby,clone,Ruby,Clone,Ruby在对象中定义了克隆。 令我惊讶的是,有些类在调用它时会引发异常。 我发现NilClass,TrueClass,falsclass,Fixnum有这种行为 1) 是否存在不允许克隆的类(至少是核心类)的完整列表? 或者有没有办法检测特定类是否支持#clone 2) 42.克隆有什么问题?您不能克隆不可变的类。也就是说,您只能有一个对象42的实例(作为Fixnum),但可以有多个“42”的实例(因为字符串是可变的)。您也不能克隆符号,因为它们类似于不可变字符串 您可以使用object_id方

Ruby在对象中定义了克隆。 令我惊讶的是,有些类在调用它时会引发异常。 我发现NilClassTrueClassfalsclassFixnum有这种行为

1) 是否存在不允许克隆的类(至少是核心类)的完整列表? 或者有没有办法检测特定类是否支持
#clone


2)
42.克隆有什么问题?

您不能克隆不可变的类。也就是说,您只能有一个对象42的实例(作为Fixnum),但可以有多个“42”的实例(因为字符串是可变的)。您也不能克隆符号,因为它们类似于不可变字符串


您可以使用object_id方法在IRB中检查这一点。(重复调用后,符号和fixnums将为您提供相同的对象id)

我认为没有正式的列表,至少除非您计算读取源代码的次数。2)不起作用的原因是应用于FixNum的优化。它们作为实际值(true、false和nil)在内部存储/传递,而不是作为指针。最简单的解决方案是只让
42.clone
返回相同的
42
,然后是不变的
obj.clone.object\u id!=obj.object\u id
将不再有效,
42.clone
实际上不会被克隆

Fixnum是一个特殊的类,受到语言的特殊处理。从程序启动时起,类可以表示的每个数字正好有一个Fixnum,并且它们被赋予了一个不占用任何额外空间的特殊表示形式——这样,基本数学操作就不会疯狂地分配和释放内存。因此,不能有多个42


对于其他人来说,他们都有一个共同点:他们都是单身。根据定义,singleton类只有一个实例,因此尝试克隆它是一个错误。

我仍然不知道如何正确地测试可克隆性,但这里有一种非常笨拙、邪恶的方法,可以使用错误捕获来测试可克隆性:

def clonable?(value)
  begin
    clone = value.clone
    true
  rescue
    false
  end
end
下面是你如何克隆甚至是不可克隆的。至少对于我已经厌倦的极少数课程

def super_mega_clone(value)
  eval(value.inspect)
end
以下是一些示例测试:

b = :b
puts "clonable? #{clonable? b}"

b = proc { b == "b" }
puts "clonable? #{clonable? b}"

b = [:a, :b, :c]
c = super_mega_clone(b)

puts "c: #{c.object_id}"
puts "b: #{b.object_id}"
puts "b == c => #{b == c}"
b.each_with_index do |value, index|
  puts "[#{index}] b: #{b[index].object_id} c: #{c[index].object_id}"
end
b[0] = :z

puts "b == c => #{b == c}"
b.each_with_index do |value, index|
  puts "[#{index}] b: #{b[index].object_id} c: #{c[index].object_id}"
end

b = :a
c = super_mega_clone(b)
puts "b: #{b.object_id} c: #{c.object_id}"

> clonable? false
> clonable? true
> c: 2153757040
> b: 2153757480
> b == c => true
> [0] b: 255528 c: 255528
> [1] b: 255688 c: 255688
> [2] b: 374568 c: 374568
> b == c => false
> [0] b: 1023528 c: 255528
> [1] b: 255688 c: 255688
> [2] b: 374568 c: 374568
> b: 255528 c: 255528
我对YARV的源代码做了一个git grep“不能克隆”的

lib/singleton.rb:    raise TypeError, "can't clone instance of singleton #{self.class}"
object.c:        rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
test/test_singleton.rb:    expected = "can't clone instance of singleton TestSingleton::SingletonTest"
第一行和第三行表示不能克隆单例


第二行是指
rb\u special\u const\u p(obj)
。但这超出了我的理解。

Rails似乎用一个“duplicable?()”方法扩展了您提到的类


易变性与此无关(事实上,您可以向Fixnum添加状态)。Fixnum的默认行为非常奇怪,特别是考虑到它确实定义了克隆方法d.class.method_?(:clone)==True我真的想知道如何测试类是否可克隆。看起来,如果一个类不允许自己被克隆,那么它应该将它从对象继承的克隆方法设置为private,这样您就只能在public_方法下测试它的存在性。对我来说,这似乎是常识。“正因为如此,不可能有超过一个42。”。为什么需要这样做呢?很完美。可复制?()也在ActiveSupport gem
obj.clone.object_id!=obj.object\u id
为真与
obj.clone.object\u id==obj.object\u id
不总是为真是不同的。前者不成立并不意味着后者不成立。