科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道跨越边界: 活动记录和 Java 编程中特定于域的语言

跨越边界: 活动记录和 Java 编程中特定于域的语言

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在这篇文章中,将学习 Ruby 提供的一些漂亮方式,可以集成干净的 DSL,让您大开眼界,用一种新的参考框架来审视 Java 的选项。

作者:baggio785 来源:CSDN 2008年2月29日

关键字: java 活动记录

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共5页)

动态地构建类

在得到了词汇和扩展类的能力之后,下一步是根据词汇动态地 扩展类。在 清单 1 中的 attr 就是这种技术的示例。现在将介绍如何实现它(感谢 Glenn Vanderburg;请参阅 参考资料)。清单 5 显示了初步的尝试:


清单 5. 动态扩展类的初步尝试


class Person
 def my_attr
  self.class.class_eval "def name; @name; end"
  self.class.class_eval "def name=(val); @name = val; end"
 end
end
 

这个示例稍微复杂了一些。self.class 返回 Person 的类。然后 class_eval 在这个类的上下文环境下计算以下字符串。第一行定义 getter,第二行定义 setter。这个示例把 name 属性添加到 Person

清单 5 有两个主要问题。首先,需要显式地调用 my_attr。还不能从类中调用它,因为它还没有定义。其次,硬编码的 name 应当是个符号。第一个问题可以通过声明一个模块并从这个模块进行继承来解决。第二个问题可以通过传递进一个符号来解决。清单 6 显示了第二次尝试:


清单 6. 动态地扩展类的第二次尝试


class Module
 def my_attr(symbol)
  class_eval "def #{symbol}; @#{symbol}; end"
  class_eval "def #{symbol}=(value); @#{symbol} = value; end"
 end
end
 

清单 6 看起来有点儿神秘,但是不用担心。可以在一点儿帮助下理解这段代码。刚才只改变了三件事:

  • 没有声明新的 Person 类,而是打开了超类 —— Ruby 的 Class

  • 没有硬编码 name,而是传递进一个叫作 symbol 的参数。用 #{symbol} 代替了 name。Ruby 用代表符号的字符串替换 #{symbol}

  • class_eval 代替了 self.class.class_eval。代码已经在类中操作了,所以不需要得到 self.class

要查看它的工作,可以在 Ruby 解释器中输入清单 7 中黑体部分的代码:


清单 7. 定义定制属性


irb(main):001:0> require "my_attr.rb"
=> true
irb(main):002:0> class Person
irb(main):003:1> my_attr :name
irb(main):004:1> end
=> nil
irb(main):005:0> person = Person.new
=> #<Person:0x2b5fb90>
irb(main):006:0> person.name = "Bruce"
=> "Bruce"
irb(main):007:0> person.name
=> "Bruce"
 

正如所期望的,可以把行为添加到任何现有类。现在看到了怎样才能把行为绑定到可以添加到类的附加功能上。这项技术就是活动目录添加高级概念(例如 belongs_tohas_many)的方式。但是活动记录没有把行为添加到类,而是添加到叫作 ActiveRecord::Base 的模块。

现在已经看到了一些相当精密的功能的作用,但是 Ruby 还能做更多支持 DSL 的事。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章