TL;DR:我如何保证我可以用
struct
构造任意 WhateverStruct::new()
?
这个:
trait Constructable {
fn new() -> Self;
}
struct Foo {
bar: u8
/* whatever else it may contain */
}
impl Constructable for Foo {
fn new(baz: u8) -> Self {
return Self { bar: baz };
}
}
不起作用,因为
new()
现在不符合 Constructable
。
背景故事:
我正在尝试通过制作链表来学习 Rust。
在 C++、Typescript 和许多其他语言中,我可以编写链表,而不必担心链表要存储的数据类型的构造函数是否存在:
template<typename T>
class LinkedListNode<T> {
public:
LinkedListNode(T data) { // This class doesn't care where T comes from or who constructed it or how it was constructed
this->data = data;
}
T data;
};
template<typename T>
class LinkedList<T> {
public:
LinkedList() {
this->head = nullptr;
}
/* whatever a linked list does */
std::shared_ptr<LinkedListNode<T>> head;
};
在 Rust 中,
struct
默认情况下似乎没有构造函数的概念,因此不保证“构造函数”(WhateverStruct::new()
)存在。
因此,我向自己保证它会存在:
trait Constructible {
fn new() -> Self;
}
所以现在我可以做:
struct LinkedListNode<'a, T> { // a lot of convincing had to be done regarding lifetimes
data: T,
next: Option<&'a LinkedListNode<'a, T>> // similar to how I needed a pointer in C++ so the struct isn't infinitely recursive
}
struct LinkedList<'a, T> { // a lot of convincinng had to be done here as well
head: Option<LinkedListNode<'a, T>>
}
到目前为止一切顺利。所以现在我想测试一下我确保“构造函数”存在的尝试是否可以通过创建一个新类型存储在我的链接列表中来实现:
struct Foo {
bar: u8
/* whatever else it may contain */
}
impl<T> Constructable for Foo {
fn new() -> Self {
//
}
}
我不知道 Foo 可能包含什么,但让我们暂时忽略它并假设我知道。我还有一个问题:
impl Constructible for Foo {
fn new(baz: u8) -> Self { // <- expected 0 params, got 1 param
return Foo { bar: baz };
}
}
现在
new
函数不再符合 Constructable
特征。
我可以做什么来保证我可以构建一些东西?
正确的方法是,就像 C++ 一样,在
T
的构造函数中采用 LinkedListNode
类型的参数(无论是实际的构造函数还是列表的 push()
方法)。另外,正确的方法是不要通过制作链表来学习 Rust——这是一个糟糕的选择;如果您觉得必须,请阅读使用太多的链表学习 Rust。
但是关于您提出的实际问题,这是可能的,尽管不如带有可变参数的 C++ 和 TypeScript 那样好。让构造函数接受一个单个通用参数。该参数可以是
()
(单位类型),以指定不需要其他参数;它可以是任何类型;或者它可以是 tuple 类型,以指定 multiple 参数。
trait Constructable<Arg> {
fn new(arg: Arg) -> Self;
}
struct Foo {
bar: u8
/* whatever else it may contain */
}
impl Constructable<u8> for Foo {
fn new(baz: u8) -> Self {
return Self { bar: baz };
}
}