2017-02-14 61 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

相關問題