我是 Rust 的新手,并且已经通过编写我的第一个玩具程序获得了一些方法,只是一个纸牌游戏实现。这是我当前的文件结构:
??? Cargo.lock
??? Cargo.toml
??? src
? ??? card.rs
? ??? deck.rs
? ??? hand.rs
? ??? main.rs
Run Code Online (Sandbox Code Playgroud)
基本构建块当然是卡片结构,它看起来像这样:
pub struct Card {
value: Value,
suit: Suit,
is_visible : bool
}
impl Card {
pub fn new(value: &Value, suit: &Suit) -> Card {
Card {...}
}
}
#[derive(Clone)]
pub enum Suit {...}
#[derive(Clone)]
pub enum Value{...}
Run Code Online (Sandbox Code Playgroud)
在deck.rs 中的deck 实现,使用card 模块:
#[path="card.rs"]
mod card;
pub use card::*;
pub struct Deck(Vec<Card>);
impl Deck {
pub fn new(n_packs: u32) -> Deck {
let mut cards = Vec::new();
...
Deck(cards)
}
pub fn deal_from_top(&mut self, n_cards: u32) -> Vec<Card>{...}
pub fn shuffle(&mut self) {...}
...
}
Run Code Online (Sandbox Code Playgroud)
非常相似的结构,Hand 在模块 hand.rs 中定义
#[path = "card.rs"]
mod card;
pub use card::*;
pub struct Hand(Vec<Card>);
impl Hand{
pub fn new(cards: Vec<Card>) -> Hand{
Hand(cards)
}
}
Run Code Online (Sandbox Code Playgroud)
在 main.rs 中,我想
最后一个让我感到非常悲伤。
这是我尝试过的:
mod hand;
mod deck;
use hand::Hand;
use deck::Deck;
fn main() {
let mut deck = Deck::new(1);
deck.shuffle();
let mut cards = deck.deal_from_top(5);
let mut hand = Hand::new(cards);
}
Run Code Online (Sandbox Code Playgroud)
这会引发编译时错误 E0308:
error[E0308]: mismatched types
--> src/main.rs:13:30
|
13 | let mut hand = Hand::new(cards);
| ^^^^^ expected struct `hand::card::Card`, found struct `deck::card::Card`
|
= note: expected struct `std::vec::Vec<hand::card::Card>`
found struct `std::vec::Vec<deck::card::Card>`
Run Code Online (Sandbox Code Playgroud)
很明显,我在理解用户定义的类型如何“导入”以供使用时缺少一些东西。
通过导入卡模块,就主要而言,甲板使用的“卡”类型和手动成为单独的类型。我不希望deck 或hand 相互引用以访问相同命名空间版本的Card。
在这种情况下,如何使卡片结构完全可重用?还是我的某种面向对象的方法是如此广泛以至于无法在惯用的 Rust 中实现?到目前为止搜索一无所获,因此感谢任何帮助。
C。
与#[path="card.rs"]
您强制您的deck
和模块在非标准位置hand
查找card
子模块。在deck.rs
and 中hand.rs
,写作mod card;
被card
视为前两个的子模块。理论上,这些子模块应该位于src/deck/card.rs
和 中src/hand/card.rs
,因此path=
可以在另一个地方找到这些子模块。
取而代之的是,您可能希望使用card
处于同一级别的模块。只需删除mod card;
这两个文件并写入pub use super::card::*;
而不是pub use::card::*;
. 最后,添加mod card;
进去,main.rs
以便main.rs
在编译器读取时发现它。
在您的解决方案中,为两个不同的子模块重用相同的文件只是一个相当于复制/粘贴的技巧,但从语言的角度来看,这两个子模块和它们提供的结构是不同的(如编译器在错误消息中所述) .