如何在多个模块中使用一个特征
How to use a trait in multiple modules
在尝试 DRY 和重新组织项目中的一些代码时,我 运行 遇到了范围和模块的问题。
src/main.rs
:
mod account;
use account::Account;
mod vacancy;
use vacancy::Vacancy;
fn main() {
let key = String::from("s3cr3t");
let uri = String::from("https://localhost:7700");
let account = Account { name: String::from("jdoe") };
account.into_meili(&uri, &key);
let vacancy = Vacancy { title: String::from("CEO") };
vacancy.into_meili(&uri, &key);
}
src/account.rs
:
pub struct Account {
name: String
}
impl IntoMeili for Account {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
src/vacancy.rs
:
pub struct Vacancy {
title: String
}
impl IntoMeili for Vacancy {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
src/into_meili.rs
:
pub trait IntoMeili {
fn into_meili(&self, uri: &String, key: &String);
}
我不知道如何将这些联系在一起。不过,我可能完全弄错了一些概念,所以可能首先是结构错误。
当我将 into_meili
引入两个模块的范围时,我需要说明 path attribute,这暗示我的结构从一开始就没有锈迹斑斑:
src/vacancy.rs
:
#[path="into_meili.rs"]
mod into_meili;
use into_meili::IntoMeili;
// ... same as above.
src/account.rs
相同。这消除了 IntoMeili 的明显 not found in this scope 错误。
此 returns src/main.rs
的错误,形式为 在 Vacancy
中找不到 account.into_meili()
的方法。建议将 IntoMeili
纳入范围。有一个奇怪的建议:use crate::account::into_meili::IntoMeili;
。再次暗示我的结构是错误的,因为我想在范围内引入 crate::into_meili::IntoMeili
?
这两个建议都不行。如果我带 use crate::account::into_meili::IntoMeili;
和 use crate::vacancy::into_meili::IntoMeili;
它会出错 private module
for into_meili
.
当我使用 mod into_meili; use into_meili::IntoMeili;
时,我仍然得到 method not found in Vacancy
,因为显然,根据这个结构,这是错误的特征。
我可能不理解 Rust 中的某个概念是正确的; Rust 有很多东西要学。显然,这些示例已大大简化,并且因为我与编译器作斗争,所以上面的代码无法编译。我在脚注中添加了一个编译版本,它只是将模块完全排除在外。
那么,我将如何构建我的项目?
- 我可以复制特征并简单地让 空缺 和 帐户 定义特征。
- 我是否完全误解或误用了特质的概念?
- 我的代码和模块结构有误吗?
- 首先在对象上定义像
fn into_meili
这样的方法,而不是让例如meili::vacancy_into_meili()
等等?
- 还有什么我完全弄错了你的微妙错误吗?
(或以上所有?)
编译示例on rust-playground:
pub trait IntoMeili {
fn into_meili(&self, uri: &String, key: &String);
}
pub struct Account {
name: String
}
impl IntoMeili for Account {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
pub struct Vacancy {
title: String
}
impl IntoMeili for Vacancy {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
fn main() {
let key = String::from("s3cr3t");
let uri = String::from("https://localhost:7700");
let account = Account { name: String::from("jdoe") };
account.into_meili(&uri, &key);
let vacancy = Vacancy { title: String::from("CEO") };
vacancy.into_meili(&uri, &key);
}
Am I structuring the code and modules wrong?
主要是您还不了解文件和模块如何link在一起。您应该永远不会必须使用#[path = ...]
属性。您的 main.rs
应该 声明 其他文件存在于 mod
:
mod account; // you already
mod vacancy; // have these
mod into_meili; // add this
然后访问into_meili
模块来实现Account
和Vacancy
的特征,你可以通过以下方式导入它:
use crate::into_meili::IntoMeili;
// or
use super::into_meili::IntoMeili;
参见:How do I import from a sibling module?
因此您的工作示例更类似于此:
// into_meili.rs
mod into_meili {
pub trait IntoMeili {
fn into_meili(&self, uri: &String, key: &String);
}
}
// account.rs
mod account {
use super::into_meili::IntoMeili;
pub struct Account {
name: String
}
impl IntoMeili for Account {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
}
// vacancy.rs
mod vacancy {
use super::into_meili::IntoMeili;
pub struct Vacancy {
title: String
}
impl IntoMeili for Vacancy {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
}
// main.rs
use account::Account;
use vacancy::Vacancy;
use into_meili::IntoMeili;
fn main() {
let key = String::from("s3cr3t");
let uri = String::from("https://localhost:7700");
let account = Account { name: String::from("jdoe") };
account.into_meili(&uri, &key);
let vacancy = Vacancy { title: String::from("CEO") };
vacancy.into_meili(&uri, &key);
}
关于更多解释,我认为博客 Clear explanation of Rust’s module system and Rust modules vs files 解释得很好。
除此之外,我觉得你的代码还不错。
Is it "rust-ish" at all to define methods like fn into_meili
on objects in the first place, rather than having e.g. a meili::vacancy_into_meili()
etc?
两者都有其用途,但如果 Account
和 Vacancy
都打算被处理 similarly/generically.
,则您将使用特征
在尝试 DRY 和重新组织项目中的一些代码时,我 运行 遇到了范围和模块的问题。
src/main.rs
:
mod account;
use account::Account;
mod vacancy;
use vacancy::Vacancy;
fn main() {
let key = String::from("s3cr3t");
let uri = String::from("https://localhost:7700");
let account = Account { name: String::from("jdoe") };
account.into_meili(&uri, &key);
let vacancy = Vacancy { title: String::from("CEO") };
vacancy.into_meili(&uri, &key);
}
src/account.rs
:
pub struct Account {
name: String
}
impl IntoMeili for Account {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
src/vacancy.rs
:
pub struct Vacancy {
title: String
}
impl IntoMeili for Vacancy {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
src/into_meili.rs
:
pub trait IntoMeili {
fn into_meili(&self, uri: &String, key: &String);
}
我不知道如何将这些联系在一起。不过,我可能完全弄错了一些概念,所以可能首先是结构错误。
当我将 into_meili
引入两个模块的范围时,我需要说明 path attribute,这暗示我的结构从一开始就没有锈迹斑斑:
src/vacancy.rs
:
#[path="into_meili.rs"]
mod into_meili;
use into_meili::IntoMeili;
// ... same as above.
src/account.rs
相同。这消除了 IntoMeili 的明显 not found in this scope 错误。
此 returns src/main.rs
的错误,形式为 在 Vacancy
中找不到 account.into_meili()
的方法。建议将 IntoMeili
纳入范围。有一个奇怪的建议:use crate::account::into_meili::IntoMeili;
。再次暗示我的结构是错误的,因为我想在范围内引入 crate::into_meili::IntoMeili
?
这两个建议都不行。如果我带 use crate::account::into_meili::IntoMeili;
和 use crate::vacancy::into_meili::IntoMeili;
它会出错 private module
for into_meili
.
当我使用 mod into_meili; use into_meili::IntoMeili;
时,我仍然得到 method not found in Vacancy
,因为显然,根据这个结构,这是错误的特征。
我可能不理解 Rust 中的某个概念是正确的; Rust 有很多东西要学。显然,这些示例已大大简化,并且因为我与编译器作斗争,所以上面的代码无法编译。我在脚注中添加了一个编译版本,它只是将模块完全排除在外。
那么,我将如何构建我的项目?
- 我可以复制特征并简单地让 空缺 和 帐户 定义特征。
- 我是否完全误解或误用了特质的概念?
- 我的代码和模块结构有误吗?
- 首先在对象上定义像
fn into_meili
这样的方法,而不是让例如meili::vacancy_into_meili()
等等? - 还有什么我完全弄错了你的微妙错误吗? (或以上所有?)
编译示例on rust-playground:
pub trait IntoMeili {
fn into_meili(&self, uri: &String, key: &String);
}
pub struct Account {
name: String
}
impl IntoMeili for Account {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
pub struct Vacancy {
title: String
}
impl IntoMeili for Vacancy {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
fn main() {
let key = String::from("s3cr3t");
let uri = String::from("https://localhost:7700");
let account = Account { name: String::from("jdoe") };
account.into_meili(&uri, &key);
let vacancy = Vacancy { title: String::from("CEO") };
vacancy.into_meili(&uri, &key);
}
Am I structuring the code and modules wrong?
主要是您还不了解文件和模块如何link在一起。您应该永远不会必须使用#[path = ...]
属性。您的 main.rs
应该 声明 其他文件存在于 mod
:
mod account; // you already
mod vacancy; // have these
mod into_meili; // add this
然后访问into_meili
模块来实现Account
和Vacancy
的特征,你可以通过以下方式导入它:
use crate::into_meili::IntoMeili;
// or
use super::into_meili::IntoMeili;
参见:How do I import from a sibling module?
因此您的工作示例更类似于此:
// into_meili.rs
mod into_meili {
pub trait IntoMeili {
fn into_meili(&self, uri: &String, key: &String);
}
}
// account.rs
mod account {
use super::into_meili::IntoMeili;
pub struct Account {
name: String
}
impl IntoMeili for Account {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
}
// vacancy.rs
mod vacancy {
use super::into_meili::IntoMeili;
pub struct Vacancy {
title: String
}
impl IntoMeili for Vacancy {
fn into_meili(&self, uri: &String, key: &String) {
println!("storing document in {} using {}", uri, key);
}
}
}
// main.rs
use account::Account;
use vacancy::Vacancy;
use into_meili::IntoMeili;
fn main() {
let key = String::from("s3cr3t");
let uri = String::from("https://localhost:7700");
let account = Account { name: String::from("jdoe") };
account.into_meili(&uri, &key);
let vacancy = Vacancy { title: String::from("CEO") };
vacancy.into_meili(&uri, &key);
}
关于更多解释,我认为博客 Clear explanation of Rust’s module system and Rust modules vs files 解释得很好。
除此之外,我觉得你的代码还不错。
Is it "rust-ish" at all to define methods like
fn into_meili
on objects in the first place, rather than having e.g. ameili::vacancy_into_meili()
etc?
两者都有其用途,但如果 Account
和 Vacancy
都打算被处理 similarly/generically.