kotlin - 如何在 rust 中解决这个继承问题?
问题描述
首先是强制性的“我是 Rust 新手”:我是。
所以我有以下问题:
我有两个(或更多)数据结构,除了它们自己的行为之外,它们都实现了一些常见的行为。我有这些结构的列表(或者更确切地说:“超类型”),我需要访问它们的一些共享行为和它们的一些个人行为。我的问题是:我如何在 Rust 中做到这一点。
为了进一步说明我的问题,我提出了 Kotlin 和 Rust 之间的代码比较。Kotlin 可以按我的意愿工作,Rust 还没有。
在 Kotlin 中,代码可能如下所示(使用普通的、旧的继承抽象):
interface Animal {
fun eat()
fun sleep()
}
class Cat(val name: String) : Animal {
fun meow() { println("meow") }
override fun eat() { println("cat $name is eating fish(or lasagne)") }
override fun sleep() { println("cat $name sleeps inside") }
}
class Lion(val tag_id: Int) : Animal {
fun roar() { println("roar") }
override fun eat() { println("lion(tag=${tag_id} is eating gazelle") }
override fun sleep() { println("lion(tag=${tag_id} sleeps outside") }
}
var animals: MutableList<Animal> = ArrayList()
fun main() {
animals.add(Cat("Garfield"))
animals.add(Lion(12))
//later:
for (animal in animals) {
animal.sleep()
if (animal is Lion)
animal.roar()
}
}
在 Rust 中,我提出了以下代码(不允许使用“instance_of”类型的函数):
trait Animal {
fn eat(&self);
fn sleep(&self);
}
struct Cat {
name: String
}
impl Cat {
fn meow(&self) { println!("meow") }
}
impl Animal for Cat {
fn eat(&self) { println!("cat {} is eating fish(or lasagne)", self.name) }
fn sleep(&self) { println!("cat {} sleeps inside", self.name) }
}
struct Lion {
tag_id: usize
}
impl Lion {
fn roar(&self) { println!("roar") }
}
impl Animal for Lion {
fn eat(&self) { println!("lion(tag={}) is eating fish(or lasagne)", self.tag_id) }
fn sleep(&self) { println!("lion(tag={}) sleeps inside", self.tag_id) }
}
fn main() {
let animals:Vec<Box<dyn Animal>> = vec![
Box::new(Cat {name: "Garfield".to_string()}),
Box::new(Lion {tag_id: 12})
];
//later:
for animal in animals {
animal.sleep()
//HOW DO I ACCESS THE CONCRETE STRUCT HERE?
}
}
我意识到这可能是一个愚蠢的问题,或者表明我“仍然被困在非 Rust 思维中”,但我在这里陷入了困境,只需要一点帮助。
解决方案
尝试用组合来代替
trait Animal {
fn voicebox(&self) -> Voicebox;
}
enum Voicebox {
CatVoicebox, LionVoicebox
}
impl Voicebox {
fn make_sound(&self) {
match *self {
Voicebox::CatVoicebox => println!("meow"),
Voicebox::LionVoicebox => println!("roar!")
}
}
}
impl Animal for Cat {
fn voicebox(&self) -> Voicebox {
Voicebox::CatVoicebox
}
}
impl Animal for Lion {
fn voicebox(&self) -> Voicebox {
Voicebox::LionVoicebox
}
}
fn main() {
let animals:Vec<Box<dyn Animal>> = vec![Box::new(Cat {name: "Garfield".to_string()}), Box::new(Lion {tag_id: 12})];
//later:
for animal in animals {
animal.sleep();
match animal.voicebox() {
vb@Voicebox::LionVoicebox => vb.make_sound(),
_ => ()
}
}
}
输出:
cat Garfield sleeps inside
lion(tag=12) sleeps inside
roar!
推荐阅读
- xamarin - 即使用户删除并重新下载应用程序,Xamarin.Essentials 也可以跟踪首次启动吗?
- java - Swift 相当于 Java 中的 MessageDigest?
- android - 通过意图拍摄照片会大大降低照片质量?
- python - 在 Pycharm 之外理解 Python 中的项目目录
- excel - 使用 InStr 在电子邮件正文中查找文本的“如果”语句很慢
- flutter - 返回主页时如何设置首选方向
- android - 有没有办法从图像(或实时摄像机)中找到颈部位置?
- rust - 如何使用可变 Vec 中的切片作为 HashMap 中的键
- php - 我如何找到具有一个共同键的两个关联数组之间的差异
- angular - cordova-plugin-inappbrowser 不能从角度工作