2017-09-04 13 views
1

Rustの特性をインターフェースのように使いたいと思います。構造体実装からの形質メソッドの使用

struct CPU { 
    r: u32, 
    pc: u32 
} 

trait Bus { 
    fn read(&self, address: u32) -> u32; 
    fn write(&self, address: u32, data: u32) -> u32; 
} 

impl CPU { 
    fn step() { 
     let opcode = self.read(0xffff); // use Bus trait method here 
    } 
} 

私が読んだり、私のCPUの実装内の書き込み実装せずにCPUの私の実装内形質メソッドを使用する方法を知っておく必要があります。私は彼らがメモリマップを定義するように別のファイルにそれらを持っていたいと思います。私はこれが単純な問題だと思う、私はちょうど私のために働く答えを見つけることができません。

+0

**優れた** [* The Rust Programming Language *](https://doc.rust-lang.org/stable/book/secondedition/)これらの入門的な質問の多くをカバーしています。これは[traitsの章](https://doc.rust-lang.org/stable/book/secondedition/ch10-02-traits.html)で説明されています。 – Shepmaster

+0

私は本の第1版を読んだが、第2版があることに気付かず、最後にそれを使用して以来、少し変わったので、私はそれを読む必要がある。私の主な問題は、継承ベースの言語からRustのコンポジションベースのデザインに切り替えることだと思います。 –

答えて

2

特性の実装は、常に独自のimplブロックにあります。

impl Bus for CPU { 
    fn read(&self, address: u32) -> u32 { unimplemented!() } 
    fn write(&self, address: u32, data: u32) -> u32 { unimplemented!() } 
} 

ほとんど知られていないトリックはimplブロックはそう長く特性とタイプの両方が、そのモジュール(持っていないimplを含むモジュールに表示されるように、あなたのクレート内の任意のモジュールに書き込むことができるということです公にする)。実装がBusCPUを定義するモジュールの下にあるサブモジュールで実行される場合、サブモジュールは自動的に両方のタイプにアクセスします。それ以外の場合は、いずれかまたは両方の宣言にpub(crate)(またはその他の形式のpub)を追加する必要があります。当然のことながら、implを含むモジュールの範囲にそれらを持って来るためには、特性とタイプをuseにするか、修飾パスを使用する必要があります。あなたがサブモジュールでimplを入れたい場合は

たとえば、あなたがいずれかを書くことができます:

use super::Bus; 
use super::CPU;  

impl Bus for CPU { 
    fn read(&self, address: u32) -> u32 { unimplemented!() } 
    fn write(&self, address: u32, data: u32) -> u32 { unimplemented!() } 
} 

または

impl super::Bus for super::CPU { 
    fn read(&self, address: u32) -> u32 { unimplemented!() } 
    fn write(&self, address: u32, data: u32) -> u32 { unimplemented!() } 
} 
+0

ありがとう!私はラストから休みを取り、これに問題があった。これは完全に機能します。 –

0

はので、ここで[OK]を、私がやろうとしたものです。

// bus controls reads and writes to/from emulated cpu 
// a trait allows me to define the interface the cpu expects 
pub trait Bus { 
    fn read(&self, size: Size, address: u32) -> u32; 
    fn write(&self, size: Size, address: u32, data: u32); 
} 

// must have an object to implement the bus on 
pub struct Mem {} // this can be filled out later 

// implement Bus trait for our Mem 
impl Bus for Mem { 
    fn read(&self, size: Size, address: u32) -> u32 { unimplemented!() } 
    fn write(&self, size: Size, address: u32, data: u32) { unimplemented!() } 
} 

// here is our cpu struct with a generic Bus trait object in it 
pub struct M68K<A: Bus> { 
    pub d: [u32; 8], 
    pub a: [u32; 8], 

    pub x: bool, // extend 
    pub n: bool, // negative 
    pub z: bool, // zero 
    pub v: bool, // overflow 
    pub c: bool, // carry 

    pub bus: A // here is the Bus trait object 
} 

// when we implement our cpu we can use the Bus trait methods, this allows 
// multiple cpu's to be created with the same or different Bus objects. 
// possibly connect 2 cpu's to the same Bus object? 
impl M68K<Mem> { 
    pub fn step(&self, cycles: u32) { 
    let x = self.bus.read(Size::Byte, 0xffff); 
    } 
} 

このコードは完了していません。私の主な目標は、自分のプロジェクトに使いやすい68k CPUエミュレータを作成することです。ここで私はすべてのファイルを1つのファイルに表示していますが、実際にはCPUのエミュレータ全体が、バスが実装されていることを知らなくても書き込むことができます。私はこれが意味をなさないことを願っています。それは私にはありません。私は再びRustを楽しんでいます!

関連する問題