首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ruby中开放类的作用域与Groovy中的MOP

Ruby中开放类的作用域与Groovy中的MOP
EN

Stack Overflow用户
提问于 2009-06-30 05:42:30
回答 3查看 696关注 0票数 1

我想弄清楚的是,我在Groovy中看到的ExpandoMetaClasses是否有某种等价性。我一直在阅读关于开放班的文章,但我不太清楚Ruby的作用域允许对类进行多大程度的修改。

借用上面博客中的一个例子,在Groovy中,我可以修改Java的String类,并向其添加如下方法:

代码语言:javascript
复制
String.metaClass.shout = {->
  return delegate.toUpperCase()
}

println "Hello MetaProgramming".shout()

// output
// HELLO METAPROGRAMMING

我认为Ruby会让您重新定义类并可能将其化名(请帮助澄清我在这一点上的误解):

代码语言:javascript
复制
class String
  def foo
    "foo"
  end
end 

puts "".foo # prints "foo"

在Groovy中,有一些方法可以将核心Java库方法的重新定义扩展到单个实例或使用类别的一组实例,这与我在Ruby中定义的混合器类似。

对特定实例或模块子集进行开放类范围的方法是什么?

如果我要安装一个重新定义了某个核心类的gem,那么该模块是否会受到影响,或者我所包含的任何.rb文件都会受到影响?

对于在Ruby和Groovy上做出一些可能的假设,我事先表示歉意,我对两者都很陌生,但我一直在试图找到两者之间的等价性。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-06-30 07:00:01

Ruby的类从未“关闭”过。所以当你说:

代码语言:javascript
复制
class String
  def omg!
    self.replace "OMG"
  end
end

在String类上定义omg!方法。与Groovy不同,Groovy需要使用特殊的元类概念,Ruby类始终是开放的。

如果您想要修改一组特定的String,可以这样做:

代码语言:javascript
复制
module Magic
  def presto
    puts "OMG A HAT!"
  end
end

class Array
  include Magic
end

x = "Hello".extend(Magic)
puts x        #=> Hello
x.presto      #=> OMG A HAT!
[].presto     #=> OMG A HAT!

def x.really?
  true
end

x.really?     #=> true

实际上,模块是可以添加到类或特定实例中的方法的集合。

因此,您可以直接打开类,也可以使用模块向类添加新方法。还可以使用模块直接打开实例或向实例添加新方法。那是因为一个类只是类的一个实例;)相当漂亮!

票数 5
EN

Stack Overflow用户

发布于 2009-06-30 07:32:55

除了Yehuda所说的,Ruby中的实例也有元类(技术上称为“单例类”),可以用class <<whatever访问。例如,要用单例类重做Yehuda的魔法示例:

代码语言:javascript
复制
x = "Hello"
class <<x
  include Magic
  def magical?
    true
  end
end
x.presto                   #=> OMG A HAT!
x.magical?                 #=> true
"Something else".magical?  #=> NoMethodError
票数 1
EN

Stack Overflow用户

发布于 2009-06-30 16:01:55

没有对类进行修改的范围。一旦修改了类,所有后续的require和下面的代码都可以访问修改后的类。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1061908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档