“猫抓鸟吃它”

时间:2014-01-19 06:52:31

标签: scala immutability traits

“Scala in Depth”有一个不寻常的例子“猫抓鸟吃它”。 http://www.manning.com/suereth/Suereth_MEAP_CH01.pdf

trait Cat
trait Bird
trait Catch
trait FullTummy
def catch(hunter: Cat, prey: Bird): Cat with Catch
def eat(consumer: Cat with Catch): Cat with FullTummy
val story = (catch _) andThen (eat _)
story(new Cat, new Bird)

我的问题是:

  1. 忽略功能部分,实现会是什么样的?

  2. 结合这样的特征或者它是人为的,这是一种现实世界的做法吗?如果在匿名课程中有10个特征要结合怎么办?

  3. 我的实现(功能部分遗漏)如下所示:

      case class Cat {
        def catchIt(_prey: Bird): Cat with Catcher = {
                new Cat with Catcher {
                    override val prey = _prey // This is ugly
                }
            }
      }
    
        case class Bird
    
        trait WithFullTummy
    
        trait Catcher {
            val prey: Bird
    
            def eat() = {
                println(s"Ate the ${prey}")
                new Cat with WithFullTummy
            }
        }
    
      val cat = new Cat                               
      val catWhoCaughtBird = cat.catchIt(new Bird)
      catWhoCaughtBird.prey
      val catWithFullTummy = catWhoCaughtBird.eat()
    

1 个答案:

答案 0 :(得分:0)

(1。)我认为以下内容可能是一个简单的实现。

trait Cat {
  val catBreed: String
  val name: String
}

trait Bird

trait Catch {
  val prey: Bird
}

trait FullTummy {
  val food: Bird
}

case class NastyCat(
  val name: String,
  val catBreed: String, 
  val prey: Bird) extends Cat with Catch

case class FullCat(
  val name: String,
  val catBreed: String, 
  val food: Bird) extends Cat with FullTummy

def catch(hunter: Cat, prey: Bird): Cat with Catch = 
  NastyCat(hunter.name, hunter.catBreed, prey)

def eat(consumer: Cat with Catch): Cat with FullTummy = 
  FullCat(consumer.name, consumer.catBreed, consumer.prey)

(2。)是的,结合这样的特征来指定匿名返回类型可能非常有用,它可以节省必须写出一个特性,它所做的就是扩展其他两个特征。更常见的是你看鸭子打字,例如def eat[T <: { val food: Bird }](consumer: T)。当特征数量变大时,为了便于阅读,人们会写出一个特征。