簡體   English   中英

將特征實現到多種類型的問題

[英]Problem implementing a trait to multiple types

作為練習,我正在嘗試創建一個溫度單位庫。

目前,以下代碼無法編譯,並且我不清楚錯誤消息。 問題似乎是類型沖突。

type Fahrenheit = f64;
type Celcius = f64;
type Kelvin = f64;


trait TemperatureUnit {
    fn to_kelvin(&self) -> Kelvin;
}

impl TemperatureUnit for Fahrenheit {
    fn to_kelvin(&self) -> Kelvin {
        (*self + 459.67) * 5/9
    }
}

impl TemperatureUnit for Celcius {
    fn to_kelvin(&self) -> Kelvin {
        *self + 273.15
    } 
}

impl TemperatureUnit for Kelvin {
    fn to_kelvin(&self) -> Kelvin {
        *self
    }
}

錯誤:

error[E0119]: conflicting implementations of trait `TemperatureUnit` for type `f64`
  --> src/lib.rs:18:1
   |
12 | impl TemperatureUnit for Fahrenheit {
   | ----------------------------------- first implementation here
...
18 | impl TemperatureUnit for Celcius {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `f64`

error[E0119]: conflicting implementations of trait `TemperatureUnit` for type `f64`
  --> src/lib.rs:24:1
   |
12 | impl TemperatureUnit for Fahrenheit {
   | ----------------------------------- first implementation here
...
24 | impl TemperatureUnit for Kelvin {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `f64`

操場

我是 Rust 的新手,所以也許這不是實現編譯器強制類型安全單元轉換的正確方法。

當你寫type時,你是在創建一個類型別名,而不是一個新類型。 例如,就像在 C++ 中使用typedef一樣。

type Fahrenheit = f64;

字面意思是“當我說'華氏'時,假裝我說的f64 ”。 不是一種新的類型,不是一種獨特的結構,字面上是一樣的。 因此,您剛剛TemperatureUnit for f64

如果您想將f64包裝在您控制下的自定義類型中,您正在尋找newtype pattern

pub struct Fahrenheit(pub f64);

現在Fahrenheit是一個獨特的結構,恰好與f64同構。 您可以使用Fahrenheit(x)構造函數從f64轉到Fahrenheit ,也可以使用my_fahrenheit.0投影返回。 如果您願意,也可以命名投影。

pub struct Fahrenheit { pub float_repr: f64 };

Rust 幾乎肯定會在內部將其編譯為實際的f64 只有一個字段的結構通常沒有開銷。 但我們實際上可以用repr(transparent)來保證這一點

#[repr(transparent)]
pub struct Fahrenheit(pub f64);

這保證了在運行時, Fahrenheitf64具有相同的表示形式(即使在它們之間定義了transmute的程度),而在編譯時它們是不同的類型。

唯一需要決定的是您希望新類型實現哪些特征。 默認情況下,它不會從f64繼承任何內容,因此您可能會在聲明之前有一個巨大的 derived derive(...)子句,包括EqOrdCloneCopy等(非詳盡列表;您知道您的用例比我好)

這里的問題是type只是一個類型的別名,它不會創建一個新的類型。 Rust 抱怨是因為這三個impl塊試圖在同一類型上實現TemperatureUnit三次。

相反,您應該聲明新類型。 下面的示例使用struct

銹操場

struct Fahrenheit(f64);
struct Celcius(f64);
struct Kelvin(f64);


trait TemperatureUnit {
    fn to_kelvin(&self) -> Kelvin;
}

impl TemperatureUnit for Fahrenheit {
    fn to_kelvin(&self) -> Kelvin {
        Kelvin((self.0 + 459.67) * 5.0/9.0)
    }
}

impl TemperatureUnit for Celcius {
    fn to_kelvin(&self) -> Kelvin {
        Kelvin(self.0 + 273.15)
    } 
}

impl TemperatureUnit for Kelvin {
    fn to_kelvin(&self) -> Kelvin {
        Kelvin(self.0)
    }
}


fn main()
{
    println!("Hey");
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM