Scala - 对象扩展抽象类并获取参数

时间:2017-04-12 12:12:09

标签: scala class object apply derived

  

// File Animal.scala

abstract class Animal {

    val name: String

    def getSomething(tClass: TypeClass): String = {
        tClass.tName.split('.').lift(0)
    }

    def apply(tClass: TypeClass): SomeOtherClassType = {
        // something... 

    }
  

//文件: DogSpike ,这用于某些特定情况(覆盖   基类val)

object DogSpike extends Animal {

  override val name: String = "Spike"
}

此调用然后有效(调用适用)
 myTransformation(() => DogSpike(this))

现在我想创建一个更通用的对象,可以传递参数,但我无法。

从Animal创建派生对象可以使用一个参数并且能够使用apply调用

object TheDog(name: String) extends Animal {

  override val name: String = "Spike"
//...
}

不确定如何隐式调用Animal.apply for TheDog对象,我可以在其中传递参数(名称)
 myTransformation(() => TheDog(this))

// also this seems to be incorrect "*Wrong top statement declaration*"
object TheDog(val n: String) extends Animal {
   override val name: String = n
//...
}

1 个答案:

答案 0 :(得分:2)

*Wrong top statement declaration*开始(我只能理解你问题的这一部分) - 你不能在对象中有构造函数,因为object是一个单例,所以你应该使用一个case类( ADT):

final case class TheDog(name: String) extends Animal

scala>TheDog("Spike")
res2_2: TheDog = TheDog("Spike")

val以及apply的随播对象会自动添加到案例类中,因此您无需在apply中定义自己的Animalcase class TheDog(val name: String)case class TheDog(name: String)相同。

我也使用trait而不是抽象类:

trait Animal {

    val name: String

    def getSomething: String = {
        "Dog: " + name
    }

}

我不了解您的TypeClass类型,但如果您真的想要类型类:

trait Animal {
  def name: String
}

final case class TheDog(name: String) extends Animal
final case class TheCat(name: String) extends Animal

implicit class RichDog(dog: TheDog){
    def getSomething: String = {
        "Dog" + dog.name
    }
}

implicit class RichCat(cat: TheCat){
    def getSomething: String = {
        "Cat: " + cat.name
    }
}

scala> TheDog("Spike").getSomething
res4_5: String = "DogSpike"
scala> TheCat("Tom").getSomething
res4_6: String = "Cat: Tom"

关于致电apply"隐含地",我不知道为什么有人需要这个,但是:

trait AnimalFactory[A <: Animal] {

   def apply(name: String)(implicit constructor: String => A) = constructor(name)

}

object TheeeDog extends AnimalFactory[TheDog]

implicit def createDog(name: String) = TheDog(name)

TheeeDog("Spike")

当然,您必须提供createDog并让其对客户端可见,但如果您可以使用ADT并在随附中定义其他必需的apply,那么它确实没有意义。对象:

  case class TheMouse(name: String)
  object TheMouse{
    def apply(isJerry: Boolean): TheMouse = if (isJerry) TheMouse("Jerry") else TheMouse("NotJerry")
  }

  TheMouse(true)

如果要向构造函数添加一些参数,只需添加它:

   class AnimalFactory(clazz: SomeClass){
       def doSomething = clazz.name

       def apply(name: String)
   }

   val dogFactory = new AnimalFactory(dogClassDescriptor)
   val catFactory = new AnimalFactory(catClassDescriptor)

   dogFactory("Spike")
   catFactory("Tom")

你甚至可以为工厂创建一个工厂(我不推荐 - 这个解决方案看起来过于复杂):

   object AnimalFactory{ //please don't use classes for that - avoiding `new` is not their purpose
     def apply(clazz: SomeClass) = new AnimalFactory(clazz)
   }
   val dogFactory = AnimalFactory(dogClassDescriptor)
   //or even `val spike = AnimalFactory(dogClassDescriptor)("Spike")`

但是,如果您可以将基础clazz作为成员或仅在包装器中提供,那么还有什么意义:

  final case class ClazzWrapper[T <: Animal](clazz: SomeClass, animal: T)