2017-02-14 66 views
1

我试图让一个new构造函数带有一个参数和两个参数,但我似乎无法弄清楚如何执行此操作。这在目前甚至可能吗?是否有可能使用不同数量的参数来重载函数(使用特征)

我现在给我一个错误多个应用项目的范围(playground

trait __Constructor1<T> { 
    fn new(T) -> Self; 
} 
trait __Constructor2<T, U> { 
    fn new(T, U) -> Self; 
} 

enum MixedInts { 
    SmallInt(i32), 
    TwoSmallInts(i32, i32), 
} 

impl __Constructor1<i32> for MixedInts { 
    fn new(__0: i32) -> MixedInts { 
     MixedInts::SmallInt(__0) 
    } 
} 
impl __Constructor2<i32, i32> for MixedInts { 
    fn new(__0: i32, __1: i32) -> MixedInts { 
     MixedInts::TwoSmallInts(__0, __1) 
    } 
} 

fn main() { 
    let x = MixedInts::new(2i32); 
    let y = MixedInts::new(2i32, 2i32); 
} 
+1

我知道你只是想创建一个小例子..但这里的特点是使用很没用。稍微改变你的例子,我[见过这种技术在一些代码库中使用](https://play.rust-lang.org/?gist=2ae7e995af81de014bd8a59971021649&version=stable&backtrace=0)。 –

+0

@SimonWhitehead我不确定你的代码应该达到什么程度。它根本不接受不同数量的参数,并且由于某种原因它创建了第二种类型而不是枚举。 – JelteF

+0

其目的是为了演示enum_的使用,以此来“超载”函数。您可以使用枚举变体将不同数量的参数传入该函数。所以它通过使用枚举作为“超载”机制来翻转你的例子 - 我只是用一个结构作为例子来强调我的例子中的枚举是主要部分。 –

回答

7

这是技术上可能的,但不是在某种程度上这是实用的。您需要使用Rust的Universal Function Call Syntax以便将呼叫歧义消除到new

fn main() { 
    let x = <MixedInts as __Constructor1<i32>>::new(2i32); 
    let y = <MixedInts as __Constructor2<i32, i32>>::new(2i32, 2i32); 
} 

铁框架有一个有趣的Modifier pattern认为完成你想要的。虽然它很聪明,但最终会让用户感到困惑。

4

Rust不支持重载的函数/方法。作为一种解决方法,您可以使用元组在单个参数中接收多个值。然后你可以定义一个特征并将其实现为该单一参数的可接受类型,并且该函数将简单地委托给特征的实现。

enum MixedInts { 
    SmallInt(i32), 
    TwoSmallInts(i32, i32), 
} 

trait IntoMixedInts { 
    fn into(self) -> MixedInts; 
} 

impl MixedInts { 
    fn new<A>(args: A) -> MixedInts 
     where A: IntoMixedInts 
    { 
     args.into() 
    } 
} 

impl IntoMixedInts for i32 { 
    fn into(self) -> MixedInts { 
     MixedInts::SmallInt(self) 
    } 
} 

impl IntoMixedInts for (i32, i32) { 
    fn into(self) -> MixedInts { 
     MixedInts::TwoSmallInts(self.0, self.1) 
    } 
} 

fn main() { 
    let x = MixedInts::new(2i32); 
    let y = MixedInts::new((2i32, 2i32)); 
} 

注:在这个例子中,你可以使用,而不是定义自己的特点的标准FromInto特质。然而,由于一致性规则(确保某种类型的特定特征只能存在一个实现的规则),它可能不适用于其他特征。

enum MixedInts { 
    SmallInt(i32), 
    TwoSmallInts(i32, i32), 
} 

impl MixedInts { 
    fn new<A>(args: A) -> MixedInts 
     where A: Into<MixedInts> 
    { 
     args.into() 
    } 
} 

impl From<i32> for MixedInts { 
    fn from(a: i32) -> MixedInts { 
     MixedInts::SmallInt(a) 
    } 
} 

impl From<(i32, i32)> for MixedInts { 
    fn from((a, b): (i32, i32)) -> MixedInts { 
     MixedInts::TwoSmallInts(a, b) 
    } 
} 

fn main() { 
    let x = MixedInts::new(2i32); 
    let y = MixedInts::new((2i32, 2i32)); 
} 
+0

注意:Rust支持通过特征重载;它似乎不如使用Into/From更实用,但支持。 –

-1

我会建议利用该From/Into性状标准库。

#[derive(PartialEq, Eq, Debug)] 
enum MixedInts { 
    SmallInt(i32), 
    TwoSmallInts(i32, i32), 
} 

impl From<i32> for MixedInts { 
    fn from(n: i32) -> Self { 
     MixedInts::SmallInt(n) 
    } 
} 

impl From<(i32, i32)> for MixedInts { 
    fn from((a, b): (i32, i32)) -> Self { 
     MixedInts::TwoSmallInts(a, b) 
    } 
} 

fn main() { 
    let x: MixedInts = 2_i32.into(); 
    assert_eq!(x, MixedInts::SmallInt(2)); 

    let y: MixedInts = (2_i32, 2_i32).into(); 
    assert_eq!(y, MixedInts::TwoSmallInts(2, 2)); 
} 

example on Rust Playground

+0

你能否澄清一下这与现有的建议使用'From'和'Into'](http://stackoverflow.com/a/42238787/155423)的区别? – Shepmaster

+0

唯一的区别是我替换了main中的代码以使用From/Into实现。 – ampron

相关问题