在方法签名中允许子类型的特征 [英] Trait allowing subtype in method signature

查看:74
本文介绍了在方法签名中允许子类型的特征的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在继承特征中定义的方法中强制执行子类型?我在什么地方放?

  trait生物体{
def reproduce(org:???):Bool
}

class Amoeba延伸生物{
def reproduce(org:Amoeba)= {//很可爱......}

}
class恐龙延伸生物{
def reproduce(org:Dinosaur)= {// so scary}
}

我的客户端代码将如下所示:

  object BoozeParty {
def gonuts()= {
val(男性有机体:有机体,女性组织)上面的代码应该工作,不管我通过getOrganisms()方法发送恐龙或变形虫,因为它返回(有机体,有机体)的元组,



我想达到的两个概念是:A b $ b b
$ b

  • Amoeba知道如何与Amoeba和恐龙交配知道如何与恐龙交配
    。因此,让他们弄清楚错综复杂的细节。

  • 恐龙不应该传给变形虫。只有变形虫才能变形虫


  • 解决方案

    请参阅 Scala School )。

      trait生物体[Self< ;: Organism [Self]] {self:Self => 
    def reproduceWith(org:Self):Boolean
    }

    class Amoeba extends Organism [Amoeba] {
    def reproduceWith(org:Amoeba)= ???
    }

    class恐龙延伸生物体[恐龙] {
    def reproduceWith(org:恐龙)= ???


    class怪物延伸恐龙

    生物体[X] 其中 X 表示它必须是生物体[X] 。这意味着只有一个 X 可以被传入,这也延伸了生物体[X]



    为了防止恐龙延伸生物体[Amoeba] 我添加了一个自我类型 self:Self => 告诉编译器这个特征应该和传入的类型混合在一起。



    mate
    $ def $ ma $ [物种< ;:有机体[物种]](男性:物种,女性:种类)=
    男性再生与女性

    用法如下:

      val a1 =新Amoeba 
    val a2 =新Amoeba

    val d1 =新恐龙$ b $ (a1,a2)
    mate(d1,d2)
    //不会编译
    // mate(a1,d1)b val d2 = new怪物

    mate

    如果您想更多地限制类型(以及更复杂的代码),您可以看看这个答案: Scala:使用具体实例的返回类型实现方法

    How do I enforce subtype in a method defined in the inherited trait? What do I place in the ??? below

    trait Organism {
     def reproduce(org:???):Bool
    }
    
    class Amoeba extends Organism {
      def reproduce(org:Amoeba) = {// so cute..}
    
    }
    class Dinosaur extends Organism {
     def reproduce(org:Dinosaur) = { // so scary} 
    }
    

    My Client Code will be something like:

    object BoozeParty {
     def gonuts() = {
        val (maleOrganism:Organism,femaleOrganism:Organism) = getOrganisms()
    
        maleOrganism.reproduce(femaleOrganism)
    
     }
    }
    

    The above code should work irrespective of me sending dinosaurs or amoebas via the method getOrganisms() as it returns a tuple of (Organism,Organism)

    The two concepts that I want to achieve are:

    • Amoeba knows how to mate with Amoeba and Dinosaur knows how to mate with Dinosaur. So let them figure out the intricate details.
    • A dinosaur should not be passed to an amoeba. Only an amoeba to an amoeba

    解决方案

    It's common to use something called F-bounded polymorphism (see Scala School).

    trait Organism[Self <: Organism[Self]] { self: Self =>
      def reproduceWith(org:Self):Boolean
    }
    
    class Amoeba extends Organism[Amoeba] {
      def reproduceWith(org:Amoeba) = ???
    }
    
    class Dinosaur extends Organism[Dinosaur] {
      def reproduceWith(org:Dinosaur) = ???
    }
    
    class Monster extends Dinosaur
    

    Organism[X] where X states that it must be an Organism[X]. This means that only an X can be passed in that also extends Organism[X].

    To prevent Dinosaur extends Organism[Amoeba] I have added a self type self: Self => that tells the compiler this trait should be mixed in with the type that was passed in.

    The mate function now looks like this:

    def mate[Species <: Organism[Species]](male:Species, female:Species) = 
      male reproduceWith female
    

    Usage is like this:

    val a1 = new Amoeba
    val a2 = new Amoeba
    
    val d1 = new Dinosaur 
    val d2 = new Monster 
    
    mate(a1, a2)
    mate(d1, d2)
    // wont compile
    // mate(a1, d1)
    

    If you want even more restriction on the types (and with that more complex code) you can take a look at this answer: Scala: implementing method with return type of concrete instance

    这篇关于在方法签名中允许子类型的特征的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆