使用泛型实现特征时特征的不兼容类型
Incompatible type for trait when implementing the trait using generics
编译以下代码:
use std::rc::Rc;
use std::cell::RefCell;
pub enum StorageType {
// ...
}
pub trait Storable {
fn get_nblocks(&self) -> usize;
fn get_storage(&self) -> Rc<RefCell<Storage>>;
}
pub trait Storage {
fn store(&mut self, data: &Storable);
fn get_type(&self) -> &StorageType;
}
pub struct DataVolume<T: Storage> {
nblocks: usize,
storage: Rc<RefCell<T>>,
}
impl<T: Storage> DataVolume<T> {
pub fn new(nblocks: usize, storage: Rc<RefCell<T>>) -> DataVolume<T> {
let this = DataVolume { nblocks: nblocks, storage: storage.clone() };
storage.borrow_mut().store(&this);
this
}
}
impl<T: Storage> Storable for DataVolume<T> {
fn get_nblocks(&self) -> usize {
self.nblocks
}
fn get_storage(&self) -> Rc<RefCell<T>> {
self.storage.clone()
}
}
给我:
src/store.rs:37:5: 39:6 error: method `get_storage` has an incompatible type
for trait: expected trait store::Storage, found type parameter [E0053]
src/store.rs:37 fn get_storage(&self) -> Rc<RefCell<T>> {
src/store.rs:38 self.storage.clone()
src/store.rs:39 }
error: aborting due to previous error
我尝试了很多东西,这就是我认为最终是正确的...
在 Rust 世界中,我的数据结构设计本身是错误的吗?
你的特征定义是:
fn get_storage(&self) -> Rc<RefCell<Storage>>
但是你的实现是
fn get_storage(&self) -> Rc<RefCell<T>>
正如编译器告诉您的那样 - 它们不兼容。 trait 定义说你将返回一个 unsized type (这可能会也可能不会,视情况而定)。该实现表示您将返回一个 特定的 类型,但将在编译时确定。
让我们选择通用解决方案,因为编译器将单态化(为您使用的每种类型生成专用代码)。这可以更快但涉及代码膨胀。将您的特征更改为:
pub trait Storable<T>
where T: Storage
{
fn get_nblocks(&self) -> usize;
fn get_storage(&self) -> Rc<RefCell<T>>;
}
整个程序看起来像 (playpen):
use std::rc::Rc;
use std::cell::RefCell;
pub enum StorageType {
// ...
}
pub trait Storable<T>
where T: Storage
{
fn get_nblocks(&self) -> usize;
fn get_storage(&self) -> Rc<RefCell<T>>;
}
pub trait Storage {
fn store(&mut self, data: &Storable<Self>);
fn get_type(&self) -> &StorageType;
}
pub struct DataVolume<T>
where T: Storage
{
nblocks: usize,
storage: Rc<RefCell<T>>,
}
impl<T> DataVolume<T>
where T: Storage
{
pub fn new(nblocks: usize, storage: Rc<RefCell<T>>) -> DataVolume<T> {
let this = DataVolume { nblocks: nblocks, storage: storage.clone() };
storage.borrow_mut().store(&this);
this
}
}
impl<T> Storable<T> for DataVolume<T>
where T: Storage
{
fn get_nblocks(&self) -> usize {
self.nblocks
}
fn get_storage(&self) -> Rc<RefCell<T>> {
self.storage.clone()
}
}
fn main() {}
编译以下代码:
use std::rc::Rc;
use std::cell::RefCell;
pub enum StorageType {
// ...
}
pub trait Storable {
fn get_nblocks(&self) -> usize;
fn get_storage(&self) -> Rc<RefCell<Storage>>;
}
pub trait Storage {
fn store(&mut self, data: &Storable);
fn get_type(&self) -> &StorageType;
}
pub struct DataVolume<T: Storage> {
nblocks: usize,
storage: Rc<RefCell<T>>,
}
impl<T: Storage> DataVolume<T> {
pub fn new(nblocks: usize, storage: Rc<RefCell<T>>) -> DataVolume<T> {
let this = DataVolume { nblocks: nblocks, storage: storage.clone() };
storage.borrow_mut().store(&this);
this
}
}
impl<T: Storage> Storable for DataVolume<T> {
fn get_nblocks(&self) -> usize {
self.nblocks
}
fn get_storage(&self) -> Rc<RefCell<T>> {
self.storage.clone()
}
}
给我:
src/store.rs:37:5: 39:6 error: method `get_storage` has an incompatible type
for trait: expected trait store::Storage, found type parameter [E0053]
src/store.rs:37 fn get_storage(&self) -> Rc<RefCell<T>> {
src/store.rs:38 self.storage.clone()
src/store.rs:39 }
error: aborting due to previous error
我尝试了很多东西,这就是我认为最终是正确的... 在 Rust 世界中,我的数据结构设计本身是错误的吗?
你的特征定义是:
fn get_storage(&self) -> Rc<RefCell<Storage>>
但是你的实现是
fn get_storage(&self) -> Rc<RefCell<T>>
正如编译器告诉您的那样 - 它们不兼容。 trait 定义说你将返回一个 unsized type (这可能会也可能不会,视情况而定)。该实现表示您将返回一个 特定的 类型,但将在编译时确定。
让我们选择通用解决方案,因为编译器将单态化(为您使用的每种类型生成专用代码)。这可以更快但涉及代码膨胀。将您的特征更改为:
pub trait Storable<T>
where T: Storage
{
fn get_nblocks(&self) -> usize;
fn get_storage(&self) -> Rc<RefCell<T>>;
}
整个程序看起来像 (playpen):
use std::rc::Rc;
use std::cell::RefCell;
pub enum StorageType {
// ...
}
pub trait Storable<T>
where T: Storage
{
fn get_nblocks(&self) -> usize;
fn get_storage(&self) -> Rc<RefCell<T>>;
}
pub trait Storage {
fn store(&mut self, data: &Storable<Self>);
fn get_type(&self) -> &StorageType;
}
pub struct DataVolume<T>
where T: Storage
{
nblocks: usize,
storage: Rc<RefCell<T>>,
}
impl<T> DataVolume<T>
where T: Storage
{
pub fn new(nblocks: usize, storage: Rc<RefCell<T>>) -> DataVolume<T> {
let this = DataVolume { nblocks: nblocks, storage: storage.clone() };
storage.borrow_mut().store(&this);
this
}
}
impl<T> Storable<T> for DataVolume<T>
where T: Storage
{
fn get_nblocks(&self) -> usize {
self.nblocks
}
fn get_storage(&self) -> Rc<RefCell<T>> {
self.storage.clone()
}
}
fn main() {}