Jör*_*tag 204
"重载"这个术语在Ruby中根本就没有意义.它基本上是"静态的基于论证的调度"的代名词,但红宝石不具备静态调度可言.因此,Ruby不支持基于参数的静态调度的原因是因为它不支持静态调度,周期.它不支持任何类型的静态分派,无论是基于参数还是其他.
现在,如果你实际上并没有特别询问有关重载的问题,而是关于基于动态参数的调度,那么答案是:因为Matz没有实现它.因为没有其他人打算提出它.因为没有其他人费心去实施它.
在与可选参数和可变长度参数列表中选择语言一般情况下,基于动态参数的分派,是非常难以得到正确的,甚至更难保持它可以理解的.即使在具有基于静态参数的调度和没有可选参数(例如Java)的语言中,有时几乎不可能分辨出一个凡人,哪个过载将被选中.
在C#中,您实际上可以将任何 3-SAT问题编码为重载决策,这意味着C#中的重载决策是NP难的.
现在尝试使用动态调度,您可以在其中保留额外的时间维度.
有些语言基于过程的所有参数动态调度,而不是面向对象的语言,它只在"隐藏"的第0个self参数上进行调度.例如,Common Lisp会调度所有参数的动态类型甚至动态值.Clojure调度所有参数的任意函数(BTW非常酷且极其强大).
但我不知道任何基于动态参数的调度的OO语言.马丁·奥德斯基说,他可能会考虑增加基于论证的派遣斯卡拉,但只有当他可以删除在同一时间超载和向后兼容都与现有的使用过载和与Java兼容的Scala代码(他特别提到Swing和AWT它发挥了一些极其复杂的技巧,几乎可以解决Java相当复杂的重载规则中令人讨厌的黑暗角落的问题.我自己有一些关于在Ruby中添加基于参数的调度的想法,但我从来没有想过如何以向后兼容的方式来实现它.
nkm*_*nkm 158
可以通过声明具有相同名称和不同签名的两个方法来实现方法重载.这些不同的签名可以是,
method(int a, int b) vs method(String a, String b)method(a) vs method(a, b)我们无法使用第一种方式实现方法重载,因为ruby(动态类型语言)中没有数据类型声明.所以定义上述方法的唯一方法是def(a,b)
使用第二个选项,看起来我们可以实现方法重载,但我们不能.假设我有两种不同数量的参数,
def method(a); end;
def method(a, b = true); end; # second argument has a default value
method(10)
# Now the method call can match the first one as well as the second one,
# so here is the problem.
Run Code Online (Sandbox Code Playgroud)
所以ruby需要在方法查找链中使用唯一名称维护一个方法.
Der*_*ins 84
我认为你正在寻找这样做的能力:
def my_method(arg1)
..
end
def my_method(arg1, arg2)
..
end
Run Code Online (Sandbox Code Playgroud)
Ruby以不同的方式支持它:
def my_method(*args)
if args.length == 1
#method 1
else
#method 2
end
end
Run Code Online (Sandbox Code Playgroud)
一个常见的模式也是将选项作为哈希传递:
def my_method(options)
if options[:arg1] and options[:arg2]
#method 2
elsif options[:arg1]
#method 1
end
end
my_method arg1: 'hello', arg2: 'world'
Run Code Online (Sandbox Code Playgroud)
希望有所帮助
方法重载在具有静态类型的语言中是有意义的,您可以在其中区分不同类型的参数
f(1)
f('foo')
f(true)
Run Code Online (Sandbox Code Playgroud)
以及不同数量的参数之间
f(1)
f(1, 'foo')
f(1, 'foo', true)
Run Code Online (Sandbox Code Playgroud)
红宝石中不存在第一个区别.Ruby使用动态类型或"鸭子打字".第二个区别可以通过默认参数或使用参数来处理:
def f(n, s = 'foo', flux_compensator = true)
...
end
def f(*args)
case args.size
when
...
when 2
...
when 3
...
end
end
Run Code Online (Sandbox Code Playgroud)
这并没有回答为什么ruby没有方法重载的问题,但是第三方库可以提供它.
该contracts.ruby库允许超载.从教程改编的示例:
class Factorial
include Contracts
Contract 1 => 1
def fact(x)
x
end
Contract Num => Num
def fact(x)
x * fact(x - 1)
end
end
# try it out
Factorial.new.fact(5) # => 120
Run Code Online (Sandbox Code Playgroud)
请注意,这实际上比Java的重载更强大,因为您可以指定要匹配的值(例如1),而不仅仅是类型.
尽管如此,你会看到性能下降; 你必须运行基准来决定你能忍受多少.
| 归档时间: |
|
| 查看次数: |
44904 次 |
| 最近记录: |