我正在学习水晶(只是为了好玩)并试图为结构实现一种 []=
方法 . 这是第一次尝试:
struct Foo
@str : String | Int32 # Have to share all the types, NOT OK
@int : Int32 | String # Have to share all the types, NOT OK
def initialize(@str = "foo", @int = 111)
end
def []=(variable, value)
{% for ivar in @type.instance_vars %}
@{{ivar}} = value if {{ivar.id.symbolize}} == variable
{% end %}
end
end
foo = Foo.new
foo[:str] = "bar" # OK
foo[:int] = 222 # OK
它的工作原理,但缺点是所有的实例变量应该共享相同的类型,否则编译器会抱怨 . 我的第二次尝试是重新实现这样的方法:
def []=(variable, value)
{% for ivar in @type.instance_vars %}
{% if ivar.id.symbolize == variable %} # ERROR: undefined macro variable 'variable'
@{{ivar}} = value
{% end %}
{% end %}
end
但这不起作用,因为 variable
里面的 {%%}
语法无法解析 . 如何克服这个问题?也许还有其他惯用的方法来实现这样的方法?
1 回答
您不需要实例变量具有所有可能类型的并集,您可以在setter方法中限制为匹配类型:
虽然这当然是可能的,但它的缺点是这些类型不匹配只能在运行时检测到 . 如果直接访问属性,则会获得更好的类型安全性(
foo.int = "string"
甚至不会编译) . 应该可以将[]=
实现为一个宏,它可能在编译时抱怨类型不匹配,但是我正在寻找你的东西 .更好的解决方案可能是使用NamedTuple . 或者你可能不知道是否有真正的用例 .