为什么Rust不支持函数或方法的重载?

6

Java中的方法重载是一个非常有帮助的功能。有时,我们需要定义具有相同名称但不同参数集的函数。我想知道为什么Rust不支持这个特性。


4
在Java中,你从不需要使用相同的名称定义一个函数,这是你的选择。 - Matthieu M.
@MatthieuM。在C++中,有时你需要使用相同的名称,因为你想将该函数用于泛型类型的模板。但这个参数并不适用于Rust。 - Sven Marnach
你可能会对这个这个感兴趣。 - Michail
2
@SvenMarnach:是的,这就是为什么我特别指定了Java。C++对于模板的重载使用被Rust用于泛型的特质所覆盖。然而,由于OP提到的是Java而不是C++,所以我不想让事情变得混乱。 - Matthieu M.
1个回答

7

我认为在某种程度上,Rust确实具有函数和方法的重载。

假设你想要实现一个abs()函数,可以接受整数或浮点数。在C++中,你可以使用

int abs(int x) { ... }
double abs(double x) { ... }

这将允许使用intdouble作为参数调用abs()函数,编译器会自动选择正确的实现。

在Rust中,您可以使用特性(trait)来代替。特性可被实现于外部类型,包括标准类型,因此这是一个合适的替代方法:

trait Abs {
    fn abs(self) -> Self;
}

impl Abs for i32 {
    fn abs(self) -> Self { ... }
}

impl Abs for f32 {
    fn abs(self) -> Self { ... }
}

这将允许您调用x.abs(),其中x可以是i32f32,编译器会为您选择正确的实现。
甚至不仅局限于编译器基于方法接收者做出决策。如果您定义一个由类型参数化的trait,则编译器将根据额外参数的类型选择方法实现。
trait Trait<T> {
    fn foo(&self, x: T);
}

struct Bar;

impl Trait<i32> for Bar {
    fn foo(&self, _: i32) {
        println!("i32");
    }
}

impl Trait<u32> for Bar {
    fn foo(&self, _: u32) {
        println!("u32");
    }
}

fn main() {
    Bar.foo(1i32);  // prints "i32"
    Bar.foo(1u32);  // prints "u32"
}

4
重载函数的参数数量有变化怎么办? - JFFIGK
@JFFIGK 这并不是真正可能的。您可以在不同的特征上拥有相同命名的函数,但编译器不会自动为您选择正确的函数 - 您需要使用完全限定的语法来选择所需的函数。而宏可以是可变参数的,因此也许这对您的用例是一个选项。 - Sven Marnach
1
我认为在某种程度上,Rust确实具有函数重载的功能。你展示了非可变参数实例成员函数重载,但没有静态成员函数重载或自由函数重载。这种“通用”的方式并不算数。 - lmat - Reinstate Monica
1
Rust不具有成员函数或静态成员函数,因为它不是面向对象的语言。无论如何,此答案中的方法可以轻松扩展为带有一个参数的自由函数和没有接收器的关联函数。它不适用于具有多个参数的函数,所以我猜它也“根本不算数”。 - Sven Marnach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接