【问题标题】:How can I implement a trait in scope for an enum of existing types for which the trait is implemented?如何在实现特征的现有类型的枚举范围内实现特征?
【发布时间】:2018-08-02 20:06:31
【问题描述】:

如何在已实现该特征的现有类型的枚举范围内实现特征?

我有这个:

extern crate pnet;

use pnet::packet::ipv4::Ipv4Packet;
use pnet::packet::ipv6::Ipv6Packet;

enum EthernetType {
    IPv4,
    ARP,
    VLAN,
    IPv6,
    Unknown(u16),
}

enum IPPacket<'a> {
    IPv4(Ipv4Packet<'a>),
    IPv6(Ipv6Packet<'a>),
}

fn ip_decode(pkt: &[u8]) -> IPPacket {
    let version = (pkt[0] & 0xf0) >> 4;
    if version == 4 {
        IPPacket::IPv4(Ipv4Packet::new(&pkt).unwrap())
    } else {
        IPPacket::IPv6(Ipv6Packet::new(&pkt).unwrap())
    }
}

fn main() {
    // Parse ethernet packet here...
    // ...
    let ip_packet = ip_decode(b"deadbeef");
    println!("{:?}", ip_packet.payload());
}

编译器抱怨我没有为我的枚举实现Packet trait

error[E0599]: no method named `payload` found for type `IPPacket<'_>` in the current scope
  --> src/main.rs:32:32
   |
14 | enum IPPacket<'a> {
   | ----------------- method `payload` not found for this
...
32 |     println!("{:?}", ip_packet.payload());
   |                                ^^^^^^^
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `payload`, perhaps you need to implement it:
           candidate #1: `pnet::packet::Packet`

我认为Packet trait 将通过Ipv4Packet&lt;'a&gt;Ipv6Packet&lt;'a&gt; 派生?

【问题讨论】:

  • 在提供的代码示例中,您还没有实现任何特征。你忘了粘贴什么吗?

标签: enums rust traits


【解决方案1】:

如何在现有类型的枚举范围内实现特征

为枚举实现特征与为结构实现特征的方式相同:

trait Noise {
    fn noise(&self);
}

enum Foo {
    Bar,
    Baz,
}

impl Noise for Foo {
    fn noise(&self) {
        match self {
            Foo::Bar => println!("bar bar bar"),
            Foo::Baz => println!("baz baz baz"),
        }
    }
}

实现特征的现有类型的枚举

我认为Packet trait 会被派生出来

事实并非如此。这样做会阻止人们在需要时为 trait 实现他们自己的代码。它也不会在所有情况下都有效,例如当一个变体没有实现它时。

trait Noise {
    fn noise(&self);
}

struct Bar;

impl Noise for Bar {
    fn noise(&self) {
        println!("bar bar bar");
    }
}

struct Baz;

impl Noise for Baz {
    fn noise(&self) {
        println!("baz baz baz");
    }
}

enum Foo {
    Bar(Bar),
    Baz(Baz),
}

impl Noise for Foo {
    fn noise(&self) {
        match self {
            Foo::Bar(bar) => bar.noise(),
            Foo::Baz(baz) => baz.noise(),
        }
    }
}

从概念上讲,可以扩展语言以支持一些注释来执行此操作,但我从未听说有人建议这样做。您可以考虑创建一个 RFC 来添加它。

也许你可以回到教你这一点的源头,从根本上纠正问题,以防止其他人以同样的方式感到困惑。

另见:

【讨论】:

  • 顺便说一句,非常感谢您向我解释如何在当前语言限制下实现枚举变体的特征。这确实与一个有趣的 RFC (github.com/rust-lang/rfcs/pull/1450) 有关使枚举变体成为一流类型,这将允许您执行 impl Noise for Foo::Bar 并为您的示例中的 match 提供语法糖。
  • @Katie 是的,我也希望该 RFC(以某种形式)有朝一日能够落地,但我认为还有很多其他功能更广泛地需要我们等待。 :-)
猜你喜欢
  • 2019-12-08
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多