如何在另一个文件中分离结构的默认特征的实现?
How can I separate the implementation of the Default trait for a structure in another file?
我的结构中有大约一百个字段,所以我想将结构定义和数据存储在单独的文件中。
具体来说,我想将定义保存在一个文件中,将 default
实现保存在另一个文件中。我想从 main.rs
访问 default
实现。我不确定如何实现它。
目录树
.
├── Cargo.toml
├── src
│ ├── config.rs
│ ├── lib
│ │ └── config_types.rs
│ └── main.rs
config_types.rs
#[derive(Debug, Copy, Clone)]
pub struct Config {
a: u8,
b: u8,
}
impl Config {
pub fn new(a: u8, b: u8) -> Self {
Config { a, b }
}
}
config.rs
#[path = "./lib/config_types.rs"] mod config_types;
use config_types::Config;
impl Default for Config {
fn default() -> Self {
Config {
a: 0b0000_0001,
b: 0b0000_0000,
}
}
}
main.rs
#[path = "./lib/config_types.rs"] mod config_types;
#[path = "./config.rs"] mod config;
use config_types::Config;
fn main() -> ! {
let config = Config::default();
}
我得到的错误:
error[E0599]: no function or associated item named `default` found for struct `config_types::Config` in the current scope
--> src/main.rs:64:26
|
64 | let config = Config::default();
| ^^^^^^^ function or associated item not found in `config_types::Config`
|
::: src/./lib/config_types.rs:2:1
|
2 | pub struct Config {
| ----------------- function or associated item `default` not found for this
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `default`, perhaps you need to implement it:
candidate #1: `Default`
如果我将默认实现移至 config_types.rs
,错误就会消失。
我怎样才能做到这一点?
- 删除
#[path]
属性。相反,使用常规模块并根据需要重新导出。
- 在整个 crate 中创建字段 public。
src/main.rs
mod lib {
pub mod config_types; // Point 1
}
mod config;
use lib::config_types; // Point 1
use config_types::Config;
fn main() {
let config = Config::default();
}
src/config.rs
use crate::config_types::Config; // Point 1
impl Default for Config {
fn default() -> Self {
Config {
a: 0b0000_0001,
b: 0b0000_0000,
}
}
}
src/lib/config_types.rs
#[derive(Debug, Copy, Clone)]
pub struct Config {
pub (crate) a: u8, // Point 2
pub (crate) b: u8, // Point 2
}
impl Config {
pub fn new(a: u8, b: u8) -> Self {
Config { a, b }
}
}
I have about a hundred fields in the structure
这听起来像是一个自动生成的文件。有关如何解决此问题的其他想法,请参阅构建脚本的 code generation example。如果它不是自动生成的文件,我看不出单独的文件如何使事情变得更容易。
我会避免创建名为 lib
的模块,因为这往往会与常见的 lib.rs
文件混淆。
如果我自己要这样做,我会翻转它,以便将生成的文件包含到手动编辑的文件中:
src/main.rs
mod config;
use config::Config;
fn main() {
let config = Config::default();
}
src/config.rs
include!("autogenerated.rs");
impl Config {
pub fn new(a: u8, b: u8) -> Self {
Config { a, b }
}
}
impl Default for Config {
fn default() -> Self {
Config {
a: 0b0000_0001,
b: 0b0000_0000,
}
}
}
src/autogenerated.rs
如果生成此文件,它可能不会存在于src
目录中!
#[derive(Debug, Copy, Clone)]
pub struct Config {
pub a: u8,
pub b: u8,
}
请注意,这些不再需要 public。
行 mod config_types;
声明了一个 new 模块。即使您通过 #[path = ...]
将它们指向同一个文件,它们也会导致 Config
:
的不同声明
crate::config_types::Config
crate::config::config_types::Config
然后您尝试将 Default
用于一个,而实际上在另一个上定义了它。
所以只能使用其中之一:
- 从
config.rs
中删除 mod config_types;
并通过 main.rs
导入它,而不是通过 use crate::config_types;
- 从
main.rs
中删除 mod config_types;
并通过 pub use config_types::Config;
从 config.rs
中导出
很少使用 #[path = ...]
。例如, config
的那个是完全不必要的,没有它也可以工作。我建议阅读 Rust Book 的 Managing Growing Projects with Packages, Crates, and Modules 章节,它很好地解释了模块以及如何正确地 import/export 项目。
我的结构中有大约一百个字段,所以我想将结构定义和数据存储在单独的文件中。
具体来说,我想将定义保存在一个文件中,将 default
实现保存在另一个文件中。我想从 main.rs
访问 default
实现。我不确定如何实现它。
目录树
.
├── Cargo.toml
├── src
│ ├── config.rs
│ ├── lib
│ │ └── config_types.rs
│ └── main.rs
config_types.rs
#[derive(Debug, Copy, Clone)]
pub struct Config {
a: u8,
b: u8,
}
impl Config {
pub fn new(a: u8, b: u8) -> Self {
Config { a, b }
}
}
config.rs
#[path = "./lib/config_types.rs"] mod config_types;
use config_types::Config;
impl Default for Config {
fn default() -> Self {
Config {
a: 0b0000_0001,
b: 0b0000_0000,
}
}
}
main.rs
#[path = "./lib/config_types.rs"] mod config_types;
#[path = "./config.rs"] mod config;
use config_types::Config;
fn main() -> ! {
let config = Config::default();
}
我得到的错误:
error[E0599]: no function or associated item named `default` found for struct `config_types::Config` in the current scope
--> src/main.rs:64:26
|
64 | let config = Config::default();
| ^^^^^^^ function or associated item not found in `config_types::Config`
|
::: src/./lib/config_types.rs:2:1
|
2 | pub struct Config {
| ----------------- function or associated item `default` not found for this
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `default`, perhaps you need to implement it:
candidate #1: `Default`
如果我将默认实现移至 config_types.rs
,错误就会消失。
我怎样才能做到这一点?
- 删除
#[path]
属性。相反,使用常规模块并根据需要重新导出。 - 在整个 crate 中创建字段 public。
src/main.rs
mod lib {
pub mod config_types; // Point 1
}
mod config;
use lib::config_types; // Point 1
use config_types::Config;
fn main() {
let config = Config::default();
}
src/config.rs
use crate::config_types::Config; // Point 1
impl Default for Config {
fn default() -> Self {
Config {
a: 0b0000_0001,
b: 0b0000_0000,
}
}
}
src/lib/config_types.rs
#[derive(Debug, Copy, Clone)]
pub struct Config {
pub (crate) a: u8, // Point 2
pub (crate) b: u8, // Point 2
}
impl Config {
pub fn new(a: u8, b: u8) -> Self {
Config { a, b }
}
}
I have about a hundred fields in the structure
这听起来像是一个自动生成的文件。有关如何解决此问题的其他想法,请参阅构建脚本的 code generation example。如果它不是自动生成的文件,我看不出单独的文件如何使事情变得更容易。
我会避免创建名为 lib
的模块,因为这往往会与常见的 lib.rs
文件混淆。
如果我自己要这样做,我会翻转它,以便将生成的文件包含到手动编辑的文件中:
src/main.rs
mod config;
use config::Config;
fn main() {
let config = Config::default();
}
src/config.rs
include!("autogenerated.rs");
impl Config {
pub fn new(a: u8, b: u8) -> Self {
Config { a, b }
}
}
impl Default for Config {
fn default() -> Self {
Config {
a: 0b0000_0001,
b: 0b0000_0000,
}
}
}
src/autogenerated.rs
如果生成此文件,它可能不会存在于src
目录中!
#[derive(Debug, Copy, Clone)]
pub struct Config {
pub a: u8,
pub b: u8,
}
请注意,这些不再需要 public。
行 mod config_types;
声明了一个 new 模块。即使您通过 #[path = ...]
将它们指向同一个文件,它们也会导致 Config
:
crate::config_types::Config
crate::config::config_types::Config
然后您尝试将 Default
用于一个,而实际上在另一个上定义了它。
所以只能使用其中之一:
- 从
config.rs
中删除mod config_types;
并通过main.rs
导入它,而不是通过use crate::config_types;
- 从
main.rs
中删除mod config_types;
并通过pub use config_types::Config;
从
config.rs
中导出
很少使用 #[path = ...]
。例如, config
的那个是完全不必要的,没有它也可以工作。我建议阅读 Rust Book 的 Managing Growing Projects with Packages, Crates, and Modules 章节,它很好地解释了模块以及如何正确地 import/export 项目。