加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Ruby元编程:如何使模块方法看到类的变量

发布时间:2020-12-17 03:42:49 所属栏目:百科 来源:网络整理
导读:例如,我有一个模块和一个类: module SimpleModule def self.class_hello puts "hello from #{@@name}" endendclass SimpleClass @@name = 'StackOverFlow' def self.test SimpleModule.class_hello endend 然后我通过调用类中的模块方法进行测试: SimpleCl
例如,我有一个模块和一个类:

module SimpleModule
  def self.class_hello
    puts "hello from #{@@name}"
  end
end

class SimpleClass
  @@name = 'StackOverFlow'
  def self.test
    SimpleModule.class_hello
  end
end

然后我通过调用类中的模块方法进行测试:

SimpleClass.test

我遇到异常:

uninitialized class variable @@name in SimpleModule (NameError)

我在这里知道,因为模块的范围与类范围不同.所以我的问题是:如何为SimpleModule范围共享SimpleClass范围?

我把元编程放在一边,因为这里只是一个简单的例子,之后我将从动态类中调用动态模块. (这就是为什么我不想使用某些关键字,如include或extend)

@编辑
实际上我想自己实现Ruby扩展.这是我已经开发的版本:

# implementation
class Class
  def custom_extend(module_name)
    module_name.methods(false).each do |method|
      define_singleton_method(method) do |*args,&block|
        module_name.send(method,*args,&block)
      end
    end
  end
end

这是我的自定义模块和测试类:

# -------------------------------------------------------------
# Demonstration
module SimpleModule
  def self.class_hello_world
    puts 'i am a simple module boss'
  end

  def self.class_hello_name
    puts "hello from #{@@name}"
  end
end

class SimpleClass
  custom_extend  SimpleModule
  @@name = 'StackOverFlow'
end

这是我的两个测试:

SimpleClass.class_hello_world  # work
SimpleClass.class_hello_name   # not work

解决方法

I just try to re-implement extend as an exercise.

ruby的extend()不能像这样工作:

module SimpleModule
  def self.class_hello_world
    puts 'i am a simple module boss'
  end

  def self.class_hello_name
    puts "hello from #{@@name}"
  end
end

class SimpleClass
  custom_extend  SimpleModule

例如,以下内容不起作用:

module Dog
  def self.greet
    puts "hello"
  end
end

class Cat
  extend Dog
end

Cat.greet

--output:--
`<main>': undefined method `greet' for Cat:Class (NoMethodError)

extend()的工作方式如下:

module Dog
  def greet
    puts "hello"
  end
end

class Cat
  extend Dog
end

Cat.greet

--output:--
hello

换句话说,extend()将模块实例方法 – 而不是模块方法(例如,自身前面的方法名称) – 插入到Cat的单例类中(这是Cat的类方法所在的位置).在ruby中,include()和extend()与模块方法无关(同样,方法名称以self开头).模块在ruby中有两种用途:

>作为命名空间,例如包含def self.method_name
>作为mixin,例如包含def some_method

include()和extend()处理#2.

以下解决方案不适用于@@变量,但试图弄清楚@@变量在ruby中展示的所有扭曲和转动是不值得的 – 只是不要使用它们.使用类实例变量,即在任何def之外指定的@variables:

def my_extend(some_module)
  singleton_class.include some_module
end

module Dog
  def greet
    puts @greeting
  end

  private
  def sayhi
    puts "hi"
  end
end

class Cat
  @greeting = "hello"
  my_extend Dog
end

Cat.greet
#Cat.sayhi  #=>`<main>': private method `sayhi' called for Cat:Class (NoMethodError) 

Cat.class_eval {sayhi}  #Change self to the Cat class so the implicit
                        #self variable that calls sayhi is equal to Cat

--output:--
hello
hi

现在,您只需要实现my_include并将其替换为in in for include.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读