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