-1

请让我知道如何使以下代码按预期工作。问题是 Scala 编译器不明白我的工厂正在返回一个具体的类,所以我的对象以后不能使用。TypeTags 或类型参数有帮助吗?还是我需要以其他方式重构代码?我(显然)是 Scala 的新手。

trait Animal
trait DomesticatedAnimal extends Animal
trait Pet extends DomesticatedAnimal {var name: String = _}
class Wolf extends Animal
class Cow extends DomesticatedAnimal
class Dog extends Pet

object Animal {
    def apply(aType: String) = {
        aType match {
            case "wolf" => new Wolf
            case "cow" => new Cow
            case "dog" => new Dog
        }
    }
}

def name(a: Pet, name: String) {
  a.name = name
  println(a +"'s name is: " + a.name)
}                                               

val d = Animal("dog")                                                     
name(d, "fred") 

最后一行代码失败,因为编译器认为d是 a Animal,而不是 a Dog

4

3 回答 3

4

您应该为每个特征的instaedapply子类创建带有方法的伴随对象。此外,像使用.AnimalAnimalname

于 2013-10-28T09:23:22.227 回答
0

I don't want to sound rude but the compiler is right about assuming that d is an Animal because that's what the Animal.apply method returns.

As already pointed out you could force the type of d with an explicit cast but it simply wouldn't be type safe. It would be leveraging your knowledge about the method implementation as a programmer, which will eventually become a source of bugs as your codebase grows and you possibly change previous code in unexpected ways.

If you need to call a Pet method then you would better use a factory method that creates Pet objects, or at least check the object type before doing the type cast, using

if (d.isInstanceOf[Pet]) name(d.asInstanceOf[Pet], "Fred")

Or better still, using pattern matching

val d = Animal("dog")
d match {
  case p: Pet => name(p, "fred")
  case _ =>
}
于 2013-10-28T23:44:02.820 回答
0

您可以这样做,而无需更改任何其他内容:

val d = Animal("dog").asInstanceOf[Dog]     //> d  : Test.Dog = Test$$anonfun$main$1$Dog$1@1030dda
name(d, "fred")                                   //> Test$$anonfun$main$1$Dog$1@1030dda's name is: fred

但是,我认为这不是一个好主意...

于 2013-10-28T15:47:22.663 回答