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