如果我有一个接受多种类型参数的函数,如何强制返回必须与输入值匹配?
尤其是当我希望一种方法可以处理任何父类型的子代时,就会出现这种情况。为了演示,请考虑“条状”的东西:
abstract struct Barlike
property bar: Int32
def initialize(@bar); end
end
abstract def make_clang_sound
abstract def serve_drinks
end
现在任何结构都可以实现这两种方法,并存储该值
struct Bar1 < Barlike
def make_clang_sound
puts "bing bang bong"
end
def serve_drinks
puts "your drink sir"
end
end
struct Bar2 < Barlike
def make_clang_sound
puts "kling klang"
end
def serve_drinks
puts "here are your drinks"
end
end
现在,如果我有一种方法想要使用该条并返回具有更新值的新方法(毕竟是结构),那么该怎么办?
def foo(arg : Barlike)
new_bar = arg.bar + 2
arg.class.new(new_bar)
end
如果传入Bar1
,则返回Bar1
;如果传入Bar2
,则返回def foo(arg : Barlike)
"howdy"
end
,但不能保证:
foo
我也将我的foo
放入一个抽象结构中,因此我需要保证Barlike
的实现者返回给定的相同类型的def foo(arg : Barlike) : arg.class
end
。
我尝试过
def foo(arg : Barlike) : typeof(arg)
end
但这是一个编译时错误(不能在那里使用arg)
我也尝试过
fields <- gBuffer(fields, byid=TRUE, width=0) # Expands the given geometry to include
the area within the specified width
zone <- fields[fields$Type == "Zone", ]
plot <- fields[fields$Type == "Plot", ]
d <- erase(zone, plot)
spplot(d, "Rx")
r <- bind(plot, d)
rd <- aggregate(r, "Rx")
spplot(rd, "Rx")
通过了,但是这里的typeof只是Barlike,而我真的需要它仅是传入的东西,只有Bar1或Bar2,等等。
宏可以帮忙吗?
答案 0 :(得分:2)
用于此目的的工具为free variables。这实际上是泛型的一种方法。
# This method returns the same type as its argument
def foo(arg : T) : T forall T
arg
end
这已经可以解决您问题的主要部分。
但是,当前无法对自由变量应用类型限制,例如将T
限制为Barlike
。
但是有一些解决方法:
def foo(arg : T) : T forall T
{% raise "arg must implement Barlike" unless T < Barlike %}
arg
end
def foo(arg : T) : T forall T
foo_impl(arg)
end
private def foo_impl(arg : Barlike)
arg
end
两种解决方法都会影响该方法的实现。无法为abstract def
指定这种类型限制。如果将foo_impl
抽象化并要求继承类来实现,而不是foo
,则数字2可能是可行的。
但是,也可以只使用带有自由变量的初始示例,而没有Barlike
限制。实际上,您可能不会获得太多收益。
答案 1 :(得分:1)
这是可行的方法:
{% for sub in Barlike.subclasses %}
struct {{sub}}
def foo() : {{sub}}
{{sub}}.new(@bar+1)
end
end
{% end %}
但是感觉像是在试图解决错误的问题。它使用#subclasses
宏为所有子结构生成一个foo。
您也可以在抽象类example中将它们声明为self方法。