Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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 为什么不应该';是否扩展由Struct.new初始化的实例?_Ruby_Rubocop - Fatal编程技术网

Ruby 为什么不应该';是否扩展由Struct.new初始化的实例?

Ruby 为什么不应该';是否扩展由Struct.new初始化的实例?,ruby,rubocop,Ruby,Rubocop,我们有一个遗留代码库,其中rubocop报告了一些我无法理解的错误: 不要扩展由Struct.new初始化的实例。 扩展它会引入多余的类级别,还可能引入 如果多次需要该文件,则会出现奇怪的错误 “多余的类级别”到底是什么意思?可能会引入什么样的“奇怪错误” (问这个问题是因为过去几年我们显然没有遇到任何这样的问题。)多余的类级别正是这个类的entendingStruct.new 到一个更详细的解释与源代码 报告还包含一个有价值的例子: Person = Struct.new(:first, :l

我们有一个遗留代码库,其中rubocop报告了一些我无法理解的错误:

不要扩展由
Struct.new
初始化的实例。 扩展它会引入多余的类级别,还可能引入 如果多次需要该文件,则会出现奇怪的错误

“多余的类级别”到底是什么意思?可能会引入什么样的“奇怪错误”


(问这个问题是因为过去几年我们显然没有遇到任何这样的问题。)

多余的类级别正是这个类的entending
Struct.new

到一个更详细的解释与源代码

报告还包含一个有价值的例子:

Person = Struct.new(:first, :last) do
  SEPARATOR = ' '.freeze
  def name
    [first, last].join(SEPARATOR)
  end
end
不等同于:

class Person < Struct.new(:first, :last)
  SEPARATOR = ' '.freeze
  def name
    [first, last].join(SEPARATOR)
  end
end
class-Person
前者创建
::Person
::SEPARATOR
,后者创建
::Person
::Person::SEPARATOR


我相信不断的查找通常被称为“奇怪的错误”。

Struct。new
创建了一个匿名类,该类恰好是
Struct
的子类:

s = Struct.new(:foo)
#=> #<Class:0x00007fdbc21a0270>

s.ancestors
#=> [#<Class:0x00007fdbc21a0270>, Struct, Enumerable, Object, Kernel, BasicObject]
这是创建
Struct
子类的常规方法

另一方面,您的遗留代码似乎包含以下内容:

class Foo < Struct.new(:foo)
end
显然,匿名类没有任何用途

就像:

class Bar
end

class Foo < Bar   # or Foo = Class.new(Bar)
end

Foo.ancestors
#=> [Foo, Bar, Object, Kernel, BasicObject]
类栏
结束
类Foo[Foo,Bar,Object,Kernel,BasicObject]
与之相反:

class Bar
end

class Foo < Class.new(Bar)
end

Foo.ancestors
#=> [Foo, #<Class:0x00007fdb870e7198>, Bar, Object, Kernel, BasicObject]
类栏
结束
Foo类<新类(条形)
结束
福娃
#=>[Foo、#、Bar、对象、内核、基本对象]

在后一个示例中,由
class.new(Bar)
返回的匿名类未分配给常量,因此既不使用也不需要。

您也可以调用
Person.Founders
来显示额外的类。前一个代码将有
[Person,Struct,…]
,而后一个代码将有
[Person,#,Struct,…]
如果没有解释好/坏的原因,那么好/坏的示例没有多大帮助。@awendt它是“坏”的,因为它创建了一个多余的类。来自以下文档:“将匿名结构子类化将创建一个永远不会使用的额外匿名类。”@Stefan Aha!现在我们有了进展…@awendt从
Struct.new
进行子类化就像编写
class Foo
而不是
class Foo
(或者更准确地说是
Foo=Class.new(Bar)
)–您将得到一个介于
Foo
Bar
之间的匿名类,该类永远不会被使用。这只是因为在ruby中基本上没有什么是不可能的。可以将该类分配给一个常量并更改祖先链的输出:)@enginersmnky只需覆盖
祖先
即可最大程度地混淆:
def Foo.祖先;super.insert(1,*ObjectSpace.each_object(Class).to_a.sample(3));结束
;-)
class Bar
end

class Foo < Bar   # or Foo = Class.new(Bar)
end

Foo.ancestors
#=> [Foo, Bar, Object, Kernel, BasicObject]
class Bar
end

class Foo < Class.new(Bar)
end

Foo.ancestors
#=> [Foo, #<Class:0x00007fdb870e7198>, Bar, Object, Kernel, BasicObject]