向“self”发送消息会导致调用初始化方法吗?

2024-03-20

我有两节课Foo and Bar:

require 'pry-byebug'
require 'fileutils'

class Foo < Pathname
  include FileUtils
  def initialize(path)
    puts "Inside Foo init..."
    super
    puts "Side effect happening..."
  end

  def some_method
    puts "Inside some_method inside Foo..."
    basename.to_s
  end
end

class Bar < Foo
end

bar = Bar.new('bar')
# binding.pry
bar.some_method

这是输出:

Inside Foo init...
Side effect happening...
Inside some_method inside Foo...
Inside Foo init...
Side effect happening...

正如您所看到的,“副作用”发生了两次。看看一个pry-byebug会议确认:

Inside Foo init...
Side effect happening...

From: /Users/max/Dropbox/work/tmp/super_test/foo.rb @ line 23 :

    18: class Bar < Foo
    19: end
    20:
    21: bar = Bar.new('bar')
    22: binding.pry
 => 23: bar.some_method

[1] pry(main)> step

From: /Users/max/Dropbox/work/tmp/super_test/foo.rb @ line 13 Foo#some_method:

    12: def some_method
 => 13:   puts "Inside some_method inside Foo..."
    14:   basename.to_s
    15: end

[1] pry(#<Bar>)> step
Inside some_method inside Foo...

From: /Users/max/Dropbox/work/tmp/super_test/foo.rb @ line 14 Foo#some_method:

    12: def some_method
    13:   puts "Inside some_method inside Foo..."
 => 14:   basename.to_s
    15: end

[1] pry(#<Bar>)> step

From: /Users/max/Dropbox/work/tmp/super_test/foo.rb @ line 7 Foo#initialize:

     6: def initialize(path)
 =>  7:   puts "Inside Foo init..."
     8:   super
     9:   puts "Side effect happening..."
    10: end

所以分解一下:

  1. 我实例化bar这是一个实例Bar它继承自Foo. Bar'超类'initialize被调用并且“副作用”发生。到目前为止,这完全是预料之中的。
  2. I call some_method on bar谁没有它,所以红宝石向上并向右并在里面找到它Foo
  3. 红宝石跳进里面some_method并找到一个向其发送消息的方法self called basename
  4. 鲁比回到Foo's' initialize方法?...

第四步完全出乎我的意料。为什么要发送消息到self导致初始化方法再次被调用?这有记录在任何地方吗?这是预期的吗?

这个可以控制吗?或者有条件地检查我是否在初始化方法内,因为我实际上是在实例化一个类,而不仅仅是随机登陆那里?例如:

class Foo < SomeClass
  def initialize args
    @args = args
    if instantiating_a_class?
      puts "Side effect happening..."
    else
      puts "Don't do anything..."
    end
  end
end

为什么向 self 发送消息会导致初始化方法再次被调用?这有记录在任何地方吗?这是预期的吗?

这就是如何basename是实现,它返回一个新实例:

/*
 * Returns the last component of the path.
 *
 * See File.basename.
 */
static VALUE
path_basename(int argc, VALUE *argv, VALUE self)
{
    VALUE str = get_strpath(self);
    VALUE fext;
    if (rb_scan_args(argc, argv, "01", &fext) == 0)
        str = rb_funcall(rb_cFile, rb_intern("basename"), 1, str);
    else
        str = rb_funcall(rb_cFile, rb_intern("basename"), 2, str, fext);
    return rb_class_new_instance(1, &str, rb_obj_class(self));
}

最后一行相当于调用new.

您可以轻松验证这一点:

class Foo < Pathname
  def initialize(path)
    puts "initialize(#{path.inspect})"
    super
  end
end

foo = Foo.new('foo/bar/baz')
# prints initialize("foo/bar/baz")
#=> #<Foo:foo/bar/baz>

foo.basename
# prints initialize("baz")
#=> #<Foo:baz>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

向“self”发送消息会导致调用初始化方法吗? 的相关文章

  • 为什么这个 Ruby 方法返回“空值表达式”错误?

    我有这个简单的方法 def is palindrome sentence raise ArgumentError new expected string unless sentence is a String safe sentence s
  • 为什么 OOP 中静态类的最佳实践有所不同?

    我目前正在阅读有关 Java 最佳实践的内容 我发现根据这本书 https rads stackoverflow com amzn click com 0321356683我们必须优先选择静态类而不是非静态类 我记得在 C 最佳实践中 我们
  • 为什么我们不能在函数式接口中重载抽象方法? (爪哇)

    所以我熟悉java中的函数式接口 以及它们与lambda表达式的使用 一个函数式接口只能包含一个抽象方法 当从 lambda 表达式使用这一孤独方法时 您不需要指定其名称 因为接口中只有一个抽象方法 编译器知道这就是您正在引用的方法 Exa
  • Mongoid - 同一外域的两个域的逆

    我试图让以下 Mongoid 关系发挥作用 但每个团队的游戏字段都是一个空数组 这不是一个有效的关系模型吗 我是否需要分开比赛 即主场比赛和客场比赛 class Team include Mongoid Document has many
  • Rails 4 - 如何链接到 PDF 文件(名称.PDF)?

    我正在生成 PDF 文件 我的链接如下所示 当我点击这个时 它会带我去 display invoice 123456789 这是一个 HTML 版本 在控制器中的操作如下 def display invoice if params invo
  • Ruby 中的并行赋值运算符

    我正在查看 Ruby 编程 书中的一个示例 def fib up to max i1 i2 1 1 parallel assignment i1 1 and i2 1 while i1 lt max yield i1 i1 i2 i2 i1
  • 从 Ruby 中的 DateTime 变量获取时间

    我在 ruby 中工作 我有一个包含数据库中今天的日期时间的对象 我只想要时间截断数据 我怎样才能得到那个 Try 日期时间 strftime http www ruby doc org stdlib 1 9 3 libdoc date r
  • 捆绑安装无法从 https://rubygems.org/ 获取规格

    我正在尝试遵循 Hartl Rails 教程 但在使用捆绑器 gem 时遇到了问题 使用命令 bundle install 或 bundle update 时 我得到以下输出 从中获取源索引https rubygems org https
  • 可以覆盖/实现的 ruby​​ 运算符列表

    是否有可以覆盖的所有 ruby 运算符的列表 不是那些不能的 Here s Ruby 运算符表 http phrogz net programmingruby language html table 18 4 方法和可重载的有 Elemen
  • 什么是抽象类? [复制]

    这个问题在这里已经有答案了 当我了解抽象类时 我说 WT H 问题 创建一个无法实例化的类有什么意义呢 为什么有人想要这样的课程 什么情况下需要抽象类 如果你明白我的意思 最常见的是用作基类或接口 某些语言有单独的interface构建 有
  • 如何计算带有偏移量的异或?

    我想用不同的偏移量进行异或计算以在计算中列出 例子 key 0 1 0 text 0 1 0 1 0 1 0 1 1 1 异或计算 key 0 text 0 key 1 text 1 key 2 text 2 key 0 text 3 ke
  • 如何在 Rails 4 中使用 params.require

    我有一个像这样的私有方法 用于有四个字段的注册表单 firstname email password and confirm password 我不知道如何检查password confirmation def user params pa
  • 从父类调用重写的虚拟方法

    假设您正在编写原始 C Object类并且您想要以下功能 object1 object2将比较引用 除非该运算符被覆盖 object1 object2将始终返回对象实际值的倒数object1 object2 所以 举例来说 如果我有一个Bu
  • 如何使用本地安装的gems执行Ruby程序?

    我已经使用安装了我的依赖项 bundle package 然后将它们传输到离线服务器并运行 gt bundle install local Using mime types 1 19 Using rest client 1 6 7 Usin
  • Heroku 部署错误

    在 Windows 环境中 尝试部署到 Heroku 时出现以下错误 C Ruby lib ruby gems 1 8 gems heroku 1 9 13 lib heroku commands base rb 32 in 没有这样的文件
  • Javascript:我应该隐藏我的实现吗?

    作为一名 C 程序员 我有一个习惯 将可以而且应该私有的东西设为私有 当 JS 类型向我公开其所有私有部分时 我总是有一种奇怪的感觉 而且这种感觉并没有被 唤起 假设我有一个类型draw方法 内部调用drawBackground and d
  • R 中使用 `UseMethod()` 与 `inherits()` 来确定对象的类

    如果我需要根据 R 对象的类以不同的方式处理它们 我可以使用if and else在单个函数内 foo lt function x if inherits x list Foo the list else if inherits x num
  • 已定义方法的 Ruby 钩子?

    我一直在谷歌上搜索这个问题 但找不到答案 这让我认为答案是否定的 但我想我会在这里问 以防有人确切知道 Ruby 是否有一个钩子来定义方法 即在模块或类上 如果没有 是否有人足够熟悉该实施的情况main对象以了解它到底如何将方法复制到Obj
  • 存根和 rspec 旧语法的问题

    我正在编写一些代码并使用 rspec 但收到警告 提示语法已过时 我不太清楚应该如何编写它 it should calculate the value correctly do mock cards Card new clubs 5 Car
  • 我可以将 MAMP (MySQL) 或 XAMPP (MySQL) 与 Ruby on Rails 3 一起使用吗?

    我可以将 MAMP MySQL 或 XAMPP MySQL 与 Ruby on Rails 3 一起使用吗 我从 MYSQL com 安装了 MySQL 但遇到了很多麻烦 所以我喜欢使用 MAMP XAMPP Mysql 有人这样做吗 另外

随机推荐