我是 Rust 的新手,并且已经通过编写我的第一个玩具程序获得了一些方法,只是一个纸牌游戏实现。这是我当前的文件结构:
??? Cargo.lock
??? Cargo.toml
??? src
?   ??? card.rs
?   ??? deck.rs
?   ??? hand.rs
?   ??? main.rs
基本构建块当然是卡片结构,它看起来像这样:
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{...}
在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) {...}
    ...
}
非常相似的结构,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)
    }
}
在 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);
}
这会引发编译时错误 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>`
很明显,我在理解用户定义的类型如何“导入”以供使用时缺少一些东西。
通过导入卡模块,就主要而言,甲板使用的“卡”类型和手动成为单独的类型。我不希望deck 或hand 相互引用以访问相同命名空间版本的Card。
在这种情况下,如何使卡片结构完全可重用?还是我的某种面向对象的方法是如此广泛以至于无法在惯用的 Rust 中实现?到目前为止搜索一无所获,因此感谢任何帮助。
C。
与#[path="card.rs"]您强制您的deck和模块在非标准位置hand查找card 子模块。在deck.rsand 中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在编译器读取时发现它。
在您的解决方案中,为两个不同的子模块重用相同的文件只是一个相当于复制/粘贴的技巧,但从语言的角度来看,这两个子模块和它们提供的结构是不同的(如编译器在错误消息中所述) .