我可以从同一个模块添加类方法和实例方法吗?

时间:2022-06-01 21:14:05

Newbie question:

I know how include and extend work, what I am wondering is if there is a way to get both class and instance methods from a single module?

我知道如何包含和扩展工作,我想知道是否有办法从单个模块获取类和实例方法?

This is how I do it with two modules:

这是我用两个模块做的方式:

module InstanceMethods
    def mod1
        "mod1"
    end
end

module ClassMethods
    def mod2
        "mod2"
    end
end

class Testing
    include InstanceMethods
    extend ClassMethods 
end

t = Testing.new
puts t.mod1
puts Testing::mod2

Thanks for taking your time ...

谢谢你抽出时间......

3 个解决方案

#1


11  

There is a common idiom for that. It makes use of included object model hook. This hook gets invoked every time when a module is included to a module/class

对此有一个共同的习语。它利用了包含的对象模型钩子。每次将模块包含在模块/类中时,都会调用此挂接

module MyExtensions
  def self.included(base)
    # base is our target class. Invoke `extend` on it and pass nested module with class methods.
    base.extend ClassMethods
  end

  def mod1
    "mod1"
  end

  module ClassMethods
    def mod2
      "mod2"
    end
  end
end

class Testing
  include MyExtensions
end

t = Testing.new
puts t.mod1
puts Testing::mod2
# >> mod1
# >> mod2

I personally like to group instance method to a nested module as well. But this is less accepted practice, as far as I know.

我个人也喜欢将实例方法分组到嵌套模块。但据我所知,这是不太被接受的做法。

module MyExtensions
  def self.included(base)
    base.extend ClassMethods
    base.include(InstanceMethods)

    # or this, if you have an old ruby and the line above doesn't work
    # base.send :include, InstanceMethods
  end

  module InstanceMethods
    def mod1
      "mod1"
    end
  end

  module ClassMethods
    def mod2
      "mod2"
    end
  end
end

#2


3  

module Foo
 def self.included(m)
   def m.show1
     p "hi"
   end
 end

 def show2
   p "hello"

 end
end

class Bar
 include Foo
end

Bar.new.show2 #=> "hello"
Bar.show1 #=> "hi"

#3


1  

Yes. It's exactly as simple as you would expect, due to the genius of ruby:

是。由于红宝石的天赋,它正如您所期望的那样简单:

module Methods
    def mod
        "mod"
    end
end

class Testing
    include Methods # will add mod as an instance method
    extend Methods # will add mod as a class method
end

t = Testing.new
puts t.mod
puts Testing::mod

Or, you could do:

或者,你可以这样做:

module Methods
    def mod1
        "mod1"
    end

    def mod2
        "mod2"
    end
end

class Testing
    include Methods # will add both mod1 and mod2 as instance methods
    extend Methods # will add both mod1 and mod2 as class methods
end

t = Testing.new
puts t.mod1
puts Testing::mod2
# But then you'd also get
puts t.mod2
puts Testing::mod1

#1


11  

There is a common idiom for that. It makes use of included object model hook. This hook gets invoked every time when a module is included to a module/class

对此有一个共同的习语。它利用了包含的对象模型钩子。每次将模块包含在模块/类中时,都会调用此挂接

module MyExtensions
  def self.included(base)
    # base is our target class. Invoke `extend` on it and pass nested module with class methods.
    base.extend ClassMethods
  end

  def mod1
    "mod1"
  end

  module ClassMethods
    def mod2
      "mod2"
    end
  end
end

class Testing
  include MyExtensions
end

t = Testing.new
puts t.mod1
puts Testing::mod2
# >> mod1
# >> mod2

I personally like to group instance method to a nested module as well. But this is less accepted practice, as far as I know.

我个人也喜欢将实例方法分组到嵌套模块。但据我所知,这是不太被接受的做法。

module MyExtensions
  def self.included(base)
    base.extend ClassMethods
    base.include(InstanceMethods)

    # or this, if you have an old ruby and the line above doesn't work
    # base.send :include, InstanceMethods
  end

  module InstanceMethods
    def mod1
      "mod1"
    end
  end

  module ClassMethods
    def mod2
      "mod2"
    end
  end
end

#2


3  

module Foo
 def self.included(m)
   def m.show1
     p "hi"
   end
 end

 def show2
   p "hello"

 end
end

class Bar
 include Foo
end

Bar.new.show2 #=> "hello"
Bar.show1 #=> "hi"

#3


1  

Yes. It's exactly as simple as you would expect, due to the genius of ruby:

是。由于红宝石的天赋,它正如您所期望的那样简单:

module Methods
    def mod
        "mod"
    end
end

class Testing
    include Methods # will add mod as an instance method
    extend Methods # will add mod as a class method
end

t = Testing.new
puts t.mod
puts Testing::mod

Or, you could do:

或者,你可以这样做:

module Methods
    def mod1
        "mod1"
    end

    def mod2
        "mod2"
    end
end

class Testing
    include Methods # will add both mod1 and mod2 as instance methods
    extend Methods # will add both mod1 and mod2 as class methods
end

t = Testing.new
puts t.mod1
puts Testing::mod2
# But then you'd also get
puts t.mod2
puts Testing::mod1