如何实施"公共/受保护/私有"方法,以及如何模拟它?

A Q*_*ker 5 ruby access-specifier

在ruby中,你可以这样做:

class Thing
  public
  def f1
    puts "f1"
  end

  private
  def f2
    puts "f2"
  end

  public
  def f3
    puts "f3"
  end

  private
  def f4
    puts "f4"
  end
end
Run Code Online (Sandbox Code Playgroud)

现在f1和f3以及public,f2和f4是私有的.内部发生了什么,允许您调用一个类方法然后更改方法定义?我怎样才能实现相同的功能(表面上是为了创建我自己的java注释)

例如...

class Thing
  fun
  def f1
    puts "hey"
  end

  notfun
  def f2
    puts "hey"
  end
end
Run Code Online (Sandbox Code Playgroud)

而fun和notfun将改变以下函数定义.

谢谢

Way*_*rad 8

你有时可以将红宝石推入espressso杯中.我们来看看如何.

这是FunNotFun模块......

module FunNotFun

  def fun
    @method_type = 'fun'
  end

  def notfun
    @method_type = 'not fun'
  end

  def method_added(id)
    return unless @method_type
    return if @bypass_method_added_hook
    orig_method = instance_method(id)
    @bypass_method_added_hook = true
    method_type = @method_type
    define_method(id) do |*args|
      orig_method.bind(self).call(*args).tap do
        puts "That was #{method_type}"
      end
    end
    @bypass_method_added_hook = false
  end

end
Run Code Online (Sandbox Code Playgroud)

...你可以用来扩展一个班级......

class Thing

  extend FunNotFun

  fun
  def f1
    puts "hey"
  end

  notfun
  def f2
    puts "hey"
  end
end
Run Code Online (Sandbox Code Playgroud)

......结果如下:

Thing.new.f1
# => hey
# => That was fun

Thing.new.f2
# => hey
# => That was not fun
Run Code Online (Sandbox Code Playgroud)

但是请参阅下面的行以获得更好的方法.


注释(参见normalocity的答案)不那么麻烦,作为一种常见的Ruby习语,将更容易传达代码的意图.以下是如何使用注释执行此操作:

module FunNotFun

  def fun(method_id)
    wrap_method(method_id, "fun")
  end

  def notfun(method_id)
    wrap_method(method_id, "not fun")
  end

  def wrap_method(method_id, type_of_method)
    orig_method = instance_method(method_id)
    define_method(method_id) do |*args|
      orig_method.bind(self).call(*args).tap do
        puts "That was #{type_of_method}"
      end
    end
  end

end
Run Code Online (Sandbox Code Playgroud)

在使用中,注释是在定义方法之后而不是之前:

class Thing

  extend FunNotFun

  def f1
    puts "hey"
  end
  fun :f1

  def f2
    puts "hey"
  end
  notfun :f2

end
Run Code Online (Sandbox Code Playgroud)

结果是一样的:

Thing.new.f1
# => hey
# => That was fun

Thing.new.f2
# => hey
# => That was not fun
Run Code Online (Sandbox Code Playgroud)