我想允许 person 对象(来自 Person 类的实例)说一种语言(这是一种存储在语言中的公共方法的集合模块):
class Person
attr_accessor :current_language
def quit
# Unselect the current language, if any:
@current_language = nil
end
end
假设语言如下:
module Language
module Japanese
def konnichiwa
"こんにちは! (from #{@current_language} instance variable)"
end
def sayounara
"さようなら。"
end
end
module French
def bonjour
"Bonjour ! (from #{@current_language} instance variable)"
end
def au_revoir
"Au revoir."
end
end
module English
def hello
"Hello! (from #{@current_language} instance variable)"
end
def bye
"Bye."
end
end
end
使用示例:
person = Person.new
person.current_language # => nil
person.hello # => may raise a nice no method error
person.current_language = :english
person.hello # => "Hello! (from english instance variable)"
person.bonjour # => may also raise a no method error
person.quit
person.current_language = :french
person.bonjour # => "Bonjour ! (from french instance variable)"
正如您所看到的,语言就像协议一样。因此,一个人可以打开特定协议,但一次只能打开一个协议。
出于模块化原因,将每种语言存储到模块中都很友好。所以我认为这种方式更合乎逻辑的Ruby方式,不是吗。
但是,我认为不可能写出这样的东西:
class Person
include "Language::#{@current_language}" unless @current_language.nil?
end
根据你的说法,这样做的最佳做法是什么?
欢迎任何评论和消息。谢谢。
此致
答案 0 :(得分:0)
如果你正确安排你的模块,你可以在Ruby中非常优雅地做到这一点。
module LanguageProxy
def method_missing(phrase)
if @current_language.respond_to?(phrase)
@current_language.send(phrase)
else
super
end
end
end
module Language
module French
def self.bonjour
"Bonjour ! (from #{@current_language} instance variable)"
end
def self.au_revoir
"Au revoir."
end
end
module English
def self.hello
"Hello! (from #{@current_language} instance variable)"
end
def self.bye
"Bye."
end
end
end
class Person
attr_accessor :current_language
include LanguageProxy
def quit
@current_language = nil
end
end
person = Person.new
person.current_language # => nil
begin
p person.hello # => may raise a nice no method error
rescue
puts "Don't know hello"
end
person.current_language = Language::English
p person.hello # => "Hello! (from english instance variable)"
begin
p person.bonjour # => may also raise a no method error
rescue
puts "Don't know bonjour"
end
person.quit
person.current_language = Language::French
p person.bonjour # => "Bonjour ! (from french instance variable)"
基本上,我们在这里所做的就是创建一个Proxy类,将Person
的未知消息转发到存储在Person
的{{1}}实例变量中的语言模块。我在这里使用的“技巧”是制作@current_language
,hello
等模块方法,而不是实例方法。然后,我将实际模块分配到bye
。
您还会注意到@current_language
模块中的@current_language
实例变量不可用Person
。如果你需要语言方法来访问这些变量,它会变得有点棘手:快速修复可能只是将它们作为参数传递。
如果您真的想使用符号来表示语言,那么您必须使用Language
做一些魔术。
输出:
C:\temp\ruby>ruby person.rb Don't know hello "Hello! (from instance variable)" Don't know bonjour "Bonjour ! (from instance variable)"
答案 1 :(得分:0)
只是为了证明你可以这样做(不是你应该这样做):
include "A::B::C".split("::").inject{|p,c| (p.class == String ? Kernel.const_get(p) : p).const_get(c)}