簡體   English   中英

Scala-對象擴展抽象類並接受參數

[英]Scala - object extends abstract class and takes parameters

//文件Animal.scala

abstract class Animal {

    val name: String

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

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

    }

// File: 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"
//...
}

不知道如何隱式調用TheDog對象的Animal.apply,我可以在其中傳遞參數(名稱)
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
//...
}

*Wrong top statement declaration* (我只能理解您問題的這一部分)-您不能在對象中使用構造函數,因為object是單例,因此您應該使用案例類(ADT):

final case class TheDog(name: String) extends Animal

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

val和伴侶的對象與apply的情況下,為類自動添加,所以你並不需要定義自己的自己的applyAnimal case 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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM