<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>chalvern (Jingwei)</title>
    <link>https://ruby-china.org/chalvern</link>
    <description>Stay hungry, stay foolish.</description>
    <language>en-us</language>
    <item>
      <title>在 Rails 里使用了 Parellel (多进程) 后出现的奇葩问题</title>
      <description>&lt;p&gt;最近开发中出现一个奇葩场景。&lt;/p&gt;
&lt;h3 id="场景"&gt;场景&lt;/h3&gt;
&lt;p&gt;Redmine 中，目前有几十个 issue，每个 issue 都需要修改状态，因为每个 issue 都是数据独立的，所以想把修改这件事放到多个进程中去做，充分利用一下硬件资源嘛。&lt;/p&gt;

&lt;p&gt;使用了 Gem Parallel&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Parallel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@issues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;in_processes: &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;issue&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;something&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;including&lt;/span&gt; &lt;span class="n"&gt;mails&lt;/span&gt; &lt;span class="n"&gt;delivering&lt;/span&gt;
&lt;span class="n"&gt;ene&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ps: 每个 issue 修改并保存成功，会发出一封邮件。&lt;/p&gt;
&lt;h3 id="遇到的两个问题"&gt;遇到的两个问题&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;相应的单元测试中，监控不到发送邮件的正确数目，目前 ActionMailer::Base.deliveries.count 的值恒为 0，推测：测试进程里的 ActionMailer::Base.deliveries 和业务逻辑里的 ActionMailer::Base.deliveries 是独立的……手工验证确实是这样的，，那么问题来了： &lt;em&gt;这种情况应该怎么写测试用例呢？&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;单元测试，理论上每运行完都会运行相应的 rollback ,保证数据库的纯正。目前发现，上面的数据是会保留的，从而干扰了一些正常的测试。。。 &lt;em&gt;这种情况是不是有方法解决呢？&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
      <author>chalvern</author>
      <pubDate>Thu, 14 Sep 2017 20:33:45 +0800</pubDate>
      <link>https://ruby-china.org/topics/34129</link>
      <guid>https://ruby-china.org/topics/34129</guid>
    </item>
    <item>
      <title>本地跑 homeland-docker 总是出现 nginx 欢迎页面</title>
      <description>&lt;h2 id="本地跑homeland-docker，发现总是跳到nginx欢迎页面"&gt;本地跑 homeland-docker，发现总是跳到 nginx 欢迎页面&lt;/h2&gt;
&lt;p&gt;研究了半天，发现是因为在 nginx.conf 中的 include 是这样写的：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# DO NOT CHANGE THIS&lt;/span&gt;
include /etc/nginx/conf.d/&lt;span class="k"&gt;*&lt;/span&gt;.conf&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但是，经过 &lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker-compose run app &lt;span class="nb"&gt;ls&lt;/span&gt; /etc/nginx/conf.d/

&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; default.conf  homeland   homeland.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;发现了这个文件夹中有个 default.conf……&lt;/p&gt;

&lt;p&gt;把 nginx.conf 中对应的语句修改成 &lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;include /etc/nginx/conf.d/homeland.conf&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;就可以了=。=&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;想问，这个问题是不是 docker image 在配置的时候忘了删这个 default.conf 了，，，纠结中……&lt;/p&gt;</description>
      <author>chalvern</author>
      <pubDate>Sat, 20 May 2017 22:08:49 +0800</pubDate>
      <link>https://ruby-china.org/topics/33027</link>
      <guid>https://ruby-china.org/topics/33027</guid>
    </item>
    <item>
      <title>Ruby 中的衔尾蛇——对象和类之间的循环关系</title>
      <description>&lt;h2 id="Ruby中的 ∞"&gt;Ruby 中的 ∞&lt;/h2&gt;
&lt;p&gt;在 Ruby 中，&lt;strong&gt;Object&lt;/strong&gt; 是所有类的超类 &lt;strong&gt;(Superclass)&lt;/strong&gt; , "Class"是所有对象的类 &lt;strong&gt;(class)&lt;/strong&gt; 。即，对任何类取有限次 &lt;strong&gt;superclass&lt;/strong&gt; ，最后都能得到 Object (其实是 BasicObject); 对任何的对象 (类也是一种对象) 取有限次 &lt;strong&gt;class&lt;/strong&gt; 最后都能得到 Class。&lt;/p&gt;

&lt;p&gt;相对于其他的编程语言，Ruby 这里存在一个比较绕的逻辑，这里先画出基本的关系图如下：
&lt;img src="http://note.youdao.com/yws/public/resource/876c1896ca4d14ca9d02022f3a421e68/xmlnote/WEBRESOURCEd932e0d47aeb2b7d8a7be07a30519940/4530" title="" alt="image"&gt;&lt;/p&gt;
&lt;h3 id="Object 与 Class 中的方法"&gt;Object 与 Class 中的方法&lt;/h3&gt;
&lt;p&gt;由于对象与类之间特殊的关系，那么在方法的角度来分析，能得出什么样好玩的结论呢？&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;. Object 中的类方法 &lt;strong&gt;(methods)&lt;/strong&gt; 与 Class 中的实例方法 &lt;strong&gt;(instance_methods)&lt;/strong&gt; 相同&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methods&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_methods&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;. Class 中的实例方法 &lt;strong&gt;(instance_methods)&lt;/strong&gt; 一部分继承于 Object 的实例方法 &lt;strong&gt;(instance_methods)&lt;/strong&gt;, 另一部分应该 &lt;strong&gt;Mixin&lt;/strong&gt; 于独立的 模块。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_methods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 56 &lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_methods&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_methods&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 44&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;. Class 中的类方法 &lt;strong&gt;(methods)&lt;/strong&gt; 主要继承于 Object 的类方法 &lt;strong&gt;(methods)&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [:nesting]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;从输出的结果来看，Class 的类方法主要继承与 Object, 但是在此之外添加了一个 &lt;strong&gt;:nesting&lt;/strong&gt; 方法。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt;. [基于前两个结论]Class 中的类方法与实例方法具有很高的重合性&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_methods&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [:nesting]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;根据个人的理解，Ruby 的元编程能力的最本质表现，是 Ruby 可以像对待对象 &lt;strong&gt;(Object)&lt;/strong&gt; 那样动态地对类 &lt;strong&gt;(Class)&lt;/strong&gt; 进行运行时编辑。在代码层面的表达，则是 类 (Class) 能够同时进行两次 &lt;strong&gt;new&lt;/strong&gt; ("Class#new"和"Class#new#new") 分别创建 &lt;strong&gt;类&lt;/strong&gt; 和 &lt;strong&gt;对象&lt;/strong&gt; .&lt;/p&gt;

&lt;p&gt;根据上面的结论，可以认为 Ruby 在设计之初主要问题之一便是统一 对象 &lt;strong&gt;(Object)&lt;/strong&gt; 与 类 &lt;strong&gt;(Class)&lt;/strong&gt; 之间的关系。而为了赋予 Ruby 元编程的能力，设计上无法避免 &lt;strong&gt;对象&lt;/strong&gt; 和 &lt;strong&gt;类&lt;/strong&gt; 在方法定义上的冗余问题 (比如一些方法同时是 &lt;strong&gt;Class&lt;/strong&gt; 的类函数和实例函数 ), 为了解决这个问题，就自然而然地引入了 模块 &lt;strong&gt;(module)&lt;/strong&gt; 的概念。&lt;/p&gt;
&lt;h2 id="Ruby中方法的调询"&gt;Ruby 中方法的调询&lt;/h2&gt;
&lt;p&gt;在 Ruby 中，最简单的方法调询路径，是当某个对象调用某个方法时，Ruby 会首先到对象所对应的类中查找是否有这个方法。但是因为继承以及混入  &lt;strong&gt;(mixin)&lt;/strong&gt; 的存在，Ruby 中存在更为复杂的方法调询路径。&lt;/p&gt;

&lt;p&gt;与 Java 等语言类似，为了调用方法，Ruby 会首先查找对象的类，然后依次查找类的超类 &lt;strong&gt;(superclass)&lt;/strong&gt; ，直到找到这个方法为止（当然如果已经找到了 &lt;strong&gt;Object&lt;/strong&gt; 还找不到一般就会报错了）。比如下面的代码：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="s1"&gt;'my_mythod()'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MySubclass&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MyClass&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MySubclass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;my_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;     &lt;span class="c1"&gt;# =&amp;gt; "my_method()"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>chalvern</author>
      <pubDate>Wed, 12 Apr 2017 22:09:31 +0800</pubDate>
      <link>https://ruby-china.org/topics/32765</link>
      <guid>https://ruby-china.org/topics/32765</guid>
    </item>
    <item>
      <title>Ruby 中的类与对象</title>
      <description>&lt;h2 id="Ruby中的类"&gt;Ruby 中的类&lt;/h2&gt;&lt;h3 id="打开类 (Open Class)"&gt;打开类 (Open Class)&lt;/h3&gt;
&lt;p&gt;在 Ruby 中，类和其他代码（对象、函数等）没有本质的区别。可以在类的定义中放任何代码：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;C&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hel"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;#输出&lt;/span&gt;
&lt;span class="c1"&gt;#hello&lt;/span&gt;
&lt;span class="c1"&gt;#hello&lt;/span&gt;
&lt;span class="c1"&gt;#hello&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ruby 会在类中运行任何可以运行的代码。但是需要重点的说明的是，上面的代码并不意味着定义了三个 C 类，比如下面的代码：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;D&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="s1"&gt;'x'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;D&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="s1"&gt;'y'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;   &lt;span class="c1"&gt;# =&amp;gt; "x"&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;y&lt;/span&gt;   &lt;span class="c1"&gt;# =&amp;gt; "y"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;从代码可以知道，上面的两个类 D 包含了两个地方定义的方法。也就是说，在第二次定义 D 类时，Ruby 能够找到第一次定义的 D 类并把新的方法（y）添加到 D 类中。在 Ruby 术语中，这叫做“打开类”&lt;strong&gt;(Open class)&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;换句话说，可以在任何时候打开一个已经存在的类，并向里面添加新的方法——包括 String 和 Array 这样的标准类。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;【注意】
Ruby 的这种特性是完全不同于其他常见语言，比如 Java、Python 等。可能未接触过 Ruby 的人会觉得这样太乱了，比如可能（而且很有可能，尤其当不同人做开发时）在不同的时间在同一个类中引入同样的一个方法，那么就容易引起混乱（一般称这种在类中全局引入方法的方式叫做猴子补丁 [Monkeypatch]）。但是，还是要补充一句，对于有自制力并且时刻记得“能力越大，责任越大”的人来说，Ruby 的这种特性能带来很牛 x 的体验。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="Ruby中的对象"&gt;Ruby 中的对象&lt;/h2&gt;&lt;h3 id="实例变量 (instance variables)"&gt;实例变量 (instance variables)&lt;/h3&gt;
&lt;p&gt;Ruby 中的对象也是一个比较有意思的东西，与 Java、Python 等也具有很大的不同。比如下面的代码：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;
    &lt;span class="vi"&gt;@v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;   &lt;span class="c1"&gt;# =&amp;gt; MyClass&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variables&lt;/span&gt;  &lt;span class="c1"&gt;# =&amp;gt; []&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;my_method&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variables&lt;/span&gt;  &lt;span class="c1"&gt;# =&amp;gt; [:@v]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 Ruby 中，对象中存在实例变量 &lt;strong&gt;(instance variables)&lt;/strong&gt; ，可以通过方法 &lt;strong&gt;instance_variables&lt;/strong&gt; 进行查看当前对象中的 &lt;strong&gt;实例变量&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;不过这里有意思的一点是，Ruby 中的实例变量和 &lt;strong&gt;类&lt;/strong&gt; 是完全不搭嘎的。也就是说，Ruby 中对象中有哪些实例变量并不受类定义的影响。比如上面代码，在调用 &lt;strong&gt;obj.my_method&lt;/strong&gt;前后，obj 中的实例变量是不一样的。或者可以这么认为：Ruby 中同一个类的不同实例对象可以具有不同的实例变量。（对于 javaer 或者 pythoner 来说，简直又一个喜闻乐见的特性）&lt;/p&gt;
&lt;h3 id="方法 (Methods)"&gt;方法 (Methods)&lt;/h3&gt;
&lt;p&gt;Ruby 中的方法和其他语言中的方法类似，对于每个实例化对象，它只保存自己的实例变量，而方法都保存在对应的类中。&lt;/p&gt;
&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;obj(OBJECT)&lt;/th&gt;
&lt;th style="text-align:center;"&gt;&lt;/th&gt;
&lt;th&gt;MyClass (CLASS)&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="/v" class="user-mention" title="@v"&gt;&lt;i&gt;@&lt;/i&gt;v&lt;/a&gt; = 1&lt;/td&gt;
&lt;td style="text-align:center;"&gt;(class)  ——&amp;gt;&lt;/td&gt;
&lt;td&gt;my_method()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(instance variables)&lt;/td&gt;
&lt;td style="text-align:center;"&gt;&lt;/td&gt;
&lt;td&gt;(Methods)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;这里需要注意的是，Ruby 中的方法同样分 类方法和实例方法，其中实例方法只能对象被调用，而类方法则只能被类调用。&lt;/p&gt;

&lt;p&gt;总结一下就是，类似于 Java 等语言，对象的实例变量在对象本地存在，而对象的方法在对象所对应的类中存在。但是和 Java 等编程语言不同的是，&lt;strong&gt;Ruby 中的类其实也是一种对象&lt;/strong&gt;。那么 Ruby 基于这个前提又能引起哪些不可思议的特性呢，后面会一一道来。&lt;/p&gt;
&lt;h2 id="Ruby中类的真实面目"&gt;Ruby 中类的真实面目&lt;/h2&gt;
&lt;p&gt;是的， &lt;strong&gt;Ruby 中的类其实是一种对象。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;因为类也是一种对象，因此所有对象的特性也是类具有的特性。比如，&lt;strong&gt;(Class)&lt;/strong&gt; 有自己的类，这个类就是——Class，举个例子，假如一个字符串可以通过 &lt;strong&gt;str#class&lt;/strong&gt; 获得它的类 String，那么 &lt;strong&gt;String&lt;/strong&gt; 作为一个对象也可以通过 &lt;strong&gt;String#class&lt;/strong&gt; 获知它自己的类。比如下面的代码：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;   &lt;span class="c1"&gt;# =&amp;gt; String&lt;/span&gt;
&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;    &lt;span class="c1"&gt;# =&amp;gt; Class&lt;/span&gt;
&lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;     &lt;span class="c1"&gt;# =&amp;gt; Class&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这是一个完全不同于 Java 等开发语言的特性。可以这么认为，在 Java 中，类的实例对象只是一个可读的类，运行时可以随意生成某类的对象，却不能随意修改类的结构；但是在 Ruby 中，类的限制规范更少，可以像对象那样在运行时定义动态的类（通过 &lt;u&gt;Class.new&lt;/u&gt; ）。或者更简单地说：在运行时，其他语言只允许读类的信息，但是 Ruby 还允许编辑类的信息。&lt;/p&gt;</description>
      <author>chalvern</author>
      <pubDate>Sun, 26 Mar 2017 10:50:33 +0800</pubDate>
      <link>https://ruby-china.org/topics/32637</link>
      <guid>https://ruby-china.org/topics/32637</guid>
    </item>
  </channel>
</rss>
