提问人:dangerousdave 提问时间:2/19/2010 最后编辑:dangerousdave 更新时间:11/14/2023 访问量:12772
如何在 mixin 方法中访问实例变量?
How do you access an instance variable within a mixin method?
问:
如何在 mixin 方法中访问实例变量?我能想到两种方法,但两者似乎都有问题。
让 mixin 方法像任何类方法一样直接访问实例变量,例如 self.text。这样做的问题在于,它限制了 mixin 方法的使用位置,并强制执行混合的类以特定方式命名特定的实例方法。
将实例变量作为参数传递给 mixin 方法,这将产生如下代码:
例
self.do_something(self.text)
或
@thing.do_something(@thing.text)
这在我看来很讨厌,并且不符合面向对象的原则。
有没有其他方法可以做到这一点?,我担心是对的吗?
答:
1赞
Kylo
2/19/2010
#1
您可以在此模块中自行提供此实例方法,但必须注意不要覆盖现有方法
示例(在您正在混合的模块中):
def text
@text ||= ""
end
评论
1赞
dangerousdave
2/19/2010
谢谢 Kylo,但这似乎仍然限制了 mixin 的使用方式。拉入它的类仍必须具有实例变量@text。
2赞
johannes
2/19/2010
#2
实例变量名称以 ruby 开头,以 @ 开头,例如。.您可以使用此名称从您包含的模块中访问它们@variable
module M
def t
@t
end
end
class A
include M
def initialize(t)
@t= t
end
end
A.new(23).t # => 23
如果要在类中未定义之前进行访问,可以这样做@t
module M
def t
instance_variable_defined?("@t") ? @t : nil
end
end
28赞
Wayne Conrad
2/19/2010
#3
一般来说,避免让 mixin 访问成员变量:这是一种非常紧密的耦合形式,可能会使未来的重构变得不必要地困难。
一个有用的策略是让 Mixin 始终通过访问器访问变量。因此,与其:
#!/usr/bin/ruby1.8
module Mixin
def do_something
p @text
end
end
class Foo
include Mixin
def initialize
@text = 'foo'
end
end
Foo.new.do_something # => "foo"
Mixin 访问 “Text” 访问器,该访问器由 including 类定义:
module Mixin
def do_something
p text
end
end
class Foo
attr_accessor :text
include Mixin
def initialize
@text = 'foo'
end
end
Foo.new.do_something # => "foo"
如果您需要将 Mixin 包含在此类中怎么办?
class Foo
def initialize
@text = "Text that has nothing to do with the mixin"
end
end
当 include 类使用相同的名称时,在 mixin 中使用通用和通用数据名称可能会导致冲突。在这种情况下,请让 mixin 查找名称不太常见的数据:
module Mixin
def do_something
p mixin_text
end
end
并让 including 类定义适当的访问器:
class Foo
include Mixin
def initialize
@text = 'text that has nothing to do with the mixin'
@something = 'text for the mixin'
end
def mixin_text
@something
end
end
Foo.new.do_something # => "text for the mixin"
通过这种方式,访问器充当混合数据和包含类数据之间的“阻抗匹配器”或“转换器”。
评论
0赞
taz mazia
9/24/2021
我可以理解不想直接访问成员变量。是否有设置访问器方法的约定?即访问器是否应该以“mixin”前缀命名?或者只是用attr_accessor来定义它?
0赞
Wayne Conrad
9/24/2021
@tazmazia 据我所知,没有任何惯例。
上一个:多步骤表单,阻止第一页清除输入
评论