如何包装其他类型并向其添加字段和方法?

时间:2015-07-19 02:57:55

标签: vector rust

我知道继承在Rust世界中是一个坏词,但是必须有某种方式,给定以下结构

struct Glyph {
    // Fields
}

有一个新的Glyphs结构,它是Vec<Glyph>方法(push等)的包装器,以及适合自己的字段和方法吗?

3 个答案:

答案 0 :(得分:4)

您可以定义类型别名(即同义词):

type Glyphs = Vec<Glyph>;

它不是一个独特的类型,因此您可以将Glyphs传递给任何需要兼容Vec的函数,包括泛型函数。

您将无法直接向此类型添加字段或固有方法。但是,你可以做的是定义一个扩展特征(即一个特性,其唯一目的是为你没有定义的类型添加方法;这里没有特殊的语法)并具有{ {1}}实现它。如果您使用模块,则必须使用Glyphs导入特征以将方法纳入范围。

use

答案 1 :(得分:3)

您可以使用DerefDerefMut,如下所示:

use std::ops::{Deref, DerefMut};

struct Glyph;

struct Glyphs(Vec<Glyph>);

impl Glyphs {
    fn new() -> Self {
        Glyphs(vec![])
    }
}

impl Deref for Glyphs {
    type Target = Vec<Glyph>;
    fn deref(&self) -> &Vec<Glyph> { &self.0 }
}

impl DerefMut for Glyphs {
    fn deref_mut(&mut self) -> &mut Vec<Glyph> { &mut self.0 }
}

fn main() {
    let mut gs = Glyphs::new();
    gs.push(Glyph);
    gs.push(Glyph);
    println!("gs.len: {}", gs.len());
}

请注意,此不是继承。一个很大的限制是你绝对无法阻止某人调用任何Vec的方法,因为他们只能手动将Glyphs解析为Vec<Glyph>。您可以通过在Glyphs上定义方法来“覆盖”这些方法,但有些人可以通过手动取消引用Glyphs来支持这些方法。

您可能还希望阅读Deref coercions chapter of the Rust Book

答案 2 :(得分:2)

在我看来,你不应该使用Deref和DerefMut来模拟继承的某些方面。它们用于编写自定义指针类型。

当你编写这样的包装器结构时,通常只需要一些Vec的功能。可能还有一些不变量需要持有。通过实施DerefDerefMut,您的Glyphs难以推理,更容易被滥用。避免公开实现细节通常也是优选的。

因此,解决方案是在Glyphs上实现您需要的功能。这些可能只是少数几个。如果你真的需要全部或大部分Vec函数和特征实现,那么封装结构不是开始时的正确选择。