我正在使用实验性功能feature(struct_inherit)
。
我有LocalPlayer
和NetPlayer
结构,他们都实现了Inputable
特性以及从虚拟结构player_num
继承Player
字段。根据比赛开始的方式,我的节目中的player_2
可以是LocalPlayer
或NetPlayer
。取决于哪一个,Inputable
特征的实施方式发生了变化。
编译器不会让我动态地为player_2
指定一个类型,具体取决于它是NetPlayer
还是LocalPlayer
。它抱怨说:
错误:不匹配的类型:预期
~player::LocalPlayer
但找到~player::NetPlayer
(预期的struct player :: LocalPlayer但找到struct player :: NetPlayer)
它也不会让我强调NetPlayer
或LocalPlayer
指向Player
指针。它声称它们不具备可扩展性。
有问题的代码示例如下:
let player1 = box player::LocalPlayer::new(0);
let player2;
if local {
player2 = box player::LocalPlayer::new(1);
} else if hosting {
player2 = box player::NetPlayer::new(1);
player2.host();
} else {
player2 = box player::NetPlayer::new(1);
player2.connect();
}
/* ... Omitted Code ... */
let input = player2.get_input(); // Trait function
结构实现如下:
pub virtual struct Player {
player_num: uint
}
pub struct LocalPlayer: Player;
pub struct NetPlayer: Player;
Rust中的结构继承非常原始;你可能不想使用它。在Rust中继承结构之间没有子类型或强制。如果你有很多具有类似字段的结构,这个功能基本上只允许你保存输入(这也是未来可能在将来添加更多功能的未来证明)。
你可以制作Player
,LocalPlayer
和NetPlayer
特质。然后,您可以获得它们之间所需的子类型行为。或者,你可以制作LocalPlayer
和NetPlayer
结构,让Player
成为一个特征。您甚至可以拥有一个PlayerImpl
结构,您可以从当前的方式继承(如果您有很多字段要共享),但是您需要为两个结构编写独立的impls。
Rust的特征与接口类似,可以组成模拟接口层次结构。它们通常是继承的替代品:
trait GetInput {
fn get_input(&self);
}
impl GetInput for Player {
fn get_input(&self) {}
}
impl GetInput for NetPlayer {
fn get_input(&self) {}
}
// Fast: interface selected at compile time
fn do_something<T: GetInput>(player: T) {
player.get_input();
}
// Flexible: interface selected at run time (virtual call)
// Use with Box<Player> (see "Trait Objects")
fn do_something_dyn(player: &dyn GetInput) {
player.get_input();
}
但是,Rust没有数据继承。要在类型之间共享公共字段,您需要一些替代的DIY解决方案(例如特征中的getter / setter或带有枚举的结构)。
我最终将Player
作为枚举实现:
pub enum Player {
Net(NetPlayer),
Local(LocalPlayer)
}
每次调用共享函数时,我都需要执行以下操作:
let input = match player2 {
player::Net(player) => player.get_input(),
player::Local(player) => player.get_input(),
};