繁体   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