Kotlin 如何解决rust中的继承问题?

Kotlin 如何解决rust中的继承问题?,kotlin,inheritance,rust,Kotlin,Inheritance,Rust,首先,我是新生锈的人:我是 因此,我有以下问题: 我有两个或两个以上的数据结构,它们除了实现自己的行为外,还实现了一些常见的行为。我有一个这些结构的列表,或者更确切地说:对于“超类型”,我需要访问它们的一些共享行为和它们的一些个人行为。 我的问题是:我如何在生锈的情况下做到这一点 为了进一步说明我的问题,我对Kotlin和Rust进行了代码比较。Kotlin按我的要求工作,Rust还没有 在Kotlin中,使用简单的旧继承抽象,代码可能如下所示: interface Animal { f

首先,我是新生锈的人:我是

因此,我有以下问题:

我有两个或两个以上的数据结构,它们除了实现自己的行为外,还实现了一些常见的行为。我有一个这些结构的列表,或者更确切地说:对于“超类型”,我需要访问它们的一些共享行为和它们的一些个人行为。 我的问题是:我如何在生锈的情况下做到这一点

为了进一步说明我的问题,我对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?
    }
}

我意识到这可能是一个愚蠢的问题,或者说明我“仍然被困在不生锈的思维中”,但我在这里有点僵局,需要的只是一点帮助。

试着用作文代替

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(),
            _ => ()
        }
    }
}

试着用作文来代替

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(),
            _ => ()
        }
    }
}

通过为每个子类型提供as_uu函数,可以实现类型检查条件:

trait Animal {
    fn eat(&self);
    fn sleep(&self);
    fn as_roaring(&self)->Option<&dyn Roaring>;
    fn as_meowing(&self)->Option<&dyn Meowing>;
}

.

可以通过为每个子类型提供as_uu函数来实现类型检查条件:

trait Animal {
    fn eat(&self);
    fn sleep(&self);
    fn as_roaring(&self)->Option<&dyn Roaring>;
    fn as_meowing(&self)->Option<&dyn Meowing>;
}

.

你可以试试这样的

使用std::any::any; 特征动物{ fn吃与自我; fn睡眠与自我; fn as_any&self->&dyn any; } 结构猫{ 名称:String } impl猫{ fn喵喵&self{println!喵喵} } 猫科动物{ fn eat&self{println!cat{}正在吃鱼或千层面,self.name} fn sleep&self{println!cat{}在里面睡觉,self.name} fn as_any&self->&dyn any{self} } 结构狮子{ tag_id:usize } impl狮子{ fn咆哮&自我{println!咆哮} } 狮子的动物{ fn eat&self{println!liontag={}正在吃鱼或千层面,self.tag_id} fn sleep&self{println!liontag={}在里面睡觉,self.tag_id} fn as_any&self->&dyn any{self} } fn干线{ 让动物:Vec=Vec[ 框::newCat{name:Garfield.to_string}, 框::newLion{tag_id:12} ]; //后来: 用于动物中的动物。iter{ 动物睡眠; 如果let Someanimal=animal.as\u any.downcast\u ref::{ 动物吼叫; } } }
你可以试试这样的

使用std::any::any; 特征动物{ fn吃与自我; fn睡眠与自我; fn as_any&self->&dyn any; } 结构猫{ 名称:String } impl猫{ fn喵喵&self{println!喵喵} } 猫科动物{ fn eat&self{println!cat{}正在吃鱼或千层面,self.name} fn sleep&self{println!cat{}在里面睡觉,self.name} fn as_any&self->&dyn any{self} } 结构狮子{ tag_id:usize } impl狮子{ fn咆哮&自我{println!咆哮} } 狮子的动物{ fn eat&self{println!liontag={}正在吃鱼或千层面,self.tag_id} fn sleep&self{println!liontag={}在里面睡觉,self.tag_id} fn as_any&self->&dyn any{self} } fn干线{ 让动物:Vec=Vec[ 框::newCat{name:Garfield.to_string}, 框::newLion{tag_id:12} ]; //后来: 用于动物中的动物。iter{ 动物睡眠; 如果let Someanimal=animal.as\u any.downcast\u ref::{ 动物吼叫; } } }
这可能会有帮助:这可能会有帮助:我想我知道你在做什么,我想它回答了我的问题,但代码没有按原样编译,游乐场链接又是我的了。@JustinBennett哦,对不起,我以为它是自动保存的。我会更新的link@JustinBennett我现在修复了链接,非常感谢-这绝对是解决我问题的一个子集。如果我发现“子类型”的单个任务是不连续的,即Cat还有单独的方法“运行”、“后退”和“跳跃”,而Lion有“游泳”、“行走”和“成为国王”,我该怎么办?@Justin如果它们有那么大的不同,那么为什么要将它们填充到同一个向量中?任何给定的设计都有可能出现不足的情况。作为一名设计师,你的任务是决定哪些属性与你真正要解决的问题相关,并选择一个具有这些属性的设计。我想我知道你在做什么,我想它回答了我的问题,但代码没有按原样编译,游乐场链接又是我的。@JustinBennett哦,对不起,我以为它是自动保存的。我会更新的link@JustinBennett我现在修复了链接,非常感谢-这绝对是解决我问题的一个子集。如果我发现“子类型”的单个任务是不连续的,即Cat还有单独的方法“运行”、“后退”和“跳跃”,而Lion有“游泳”、“行走”和“成为国王”,我该怎么办?@Justin如果它们有那么大的不同,那么为什么要将它们填充到同一个向量中?任何给定的设计都有可能出现不足的情况。作为设计师,你的任务是 确定哪些属性与您真正要解决的问题相关,然后选择具有这些属性的设计。
    for animal in animals {
        animal.sleep();
        if let Some(roaring) = animal.as_roaring() {
          roaring.roar();
        }
    }