我是否正确使用继承,借用指针和显式生命周期注释?

时间:2014-08-21 23:58:16

标签: memory-management rust

我正在学习Rust,来自几乎完全垃圾收集的背景。因此,我想确保在编写第一个程序时我正站起来。

Rust网站上的教程说我应该怀疑使用不是&的指针。考虑到这一点,这就是我在我的小班级层次结构中所得到的(名称改为保护无辜)。要点是,我有两个不同的实体,让我们说Derived1Derived2,它们共享一些行为和结构。我将公共数据放入Foo结构并将常见行为转换为Fooish特征:

struct Foo<'a> {
    name:       &'a str,
    an_array:   &'a [AnEnumType],
    /* etc. */
}

struct Derived1<'a> {
    foo:         &'a Foo<'a>,
    other_stuff: &'a str,
}
struct Derived2<'a> {
    foo: &'a Foo<'a>,
    /* etc. */
}

trait Fooish<'a> {
    fn new(foo: &'a Foo<'a>) -> Self;
    /* etc. */
}

impl<'a> Fooish<'a> for Derived1<'a> {
    fn new(foo: &'a Foo<'a>) -> Derived1<'a> {
        Derived1 { foo: foo, other_stuff: "bar" }
    }
    /* etc. */
}

/* and so forth for Derived2 */

我的问题:

  1. 我是&#34;在Rust&#34;做继承?或多或少的惯用语?
  2. 在这里使用&指针作为结构字段是否正确? (例如对于字符串数据,以及其大小因实例而异的数组字段?Foo中的Derived怎么办?)
  3. 如果#2的回答是“是”,那么我需要明确的终身注释,对吗?
  4. 在我的例子中,到处都有这么多终身注释是否常见?
  5. 谢谢!

1 个答案:

答案 0 :(得分:2)

我会说这根本不是惯用语,但有时 任务需要逐步摆脱惯用法,目前尚不清楚这是否真的是这种情况。

我建议你不要使用在类和继承方面运行的OO语言的想法 - 它们在Rust中无法正常工作。相反,您应该根据所有权来考虑您的数据:如果给定的结构拥有数据,请问自己一个问题?换句话说,数据是自然属于结构还是可以在某处独立使用?

如果您将此推理应用于您的结构:

struct Foo<'a> {
    name:       &'a str,
    an_array:   &'a [AnEnumType],
    /* etc. */
}

struct Derived1<'a> {
    foo:         &'a Foo<'a>,
    other_stuff: &'a str,
}

struct Derived2<'a> {
    foo: &'a Foo<'a>,
    /* etc. */
}

你会发现使用引用编码继承是没有意义的。如果Derived1引用了Foo,那么暗示这个Foo是在其他地方创建的,Derived1只是借用了一段时间。虽然这个可能是你真正想要的东西,但这并不是继承的工作原理:继承的结构/类通常包含其中的“父”内容;换句话说,他们拥有他们的父数据,所以这将是更合适的结构:

struct Foo<'a> {
    name:       &'a str,
    an_array:   &'a [AnEnumType],
    /* etc. */
}

struct Derived1<'a> {
    foo:         Foo<'a>
    other_stuff: &'a str,
}

struct Derived2<'a> {
    foo: Foo<'a>,
    /* etc. */
}

请注意,Derived*结构现在包含Foo

对于字符串和数组(实际上是字符串切片和数组切片),是的,如果要将它们保存在结构中,则必须使用生命周期注释。但是,通常不会发生这种情况,而且,基于所有权设计结构通常有助于确定这应该是切片还是动态分配的StringVec。有一个nice tutorial on strings,当你需要使用自有字符串和需要切片时,它解释了其他所有内容。相同的推理适用于&[T] / Vec<T>。简而言之,如果您的struct 拥有字符串/数组,则必须使用String / Vec。否则,请考虑使用切片。