2017-04-12 8 views
0

// Datei Animal.scalaScala - Objekt erweitert abstrakte Klasse und nimmt Parameter

abstract class Animal { 

    val name: String 

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

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

    } 

// Datei: DogSpike, ist dies für einige spezielle Fälle verwendet (überschreibt Basis Klasse val)

object DogSpike extends Animal { 

    override val name: String = "Spike" 
} 

dieser Aufruf funktioniert dann (Anrufe gelten)
myTransformation(() => DogSpike(this))

Jetzt würde ich ein allgemeineres Objekt erstellen möchten, dass man Argumente übergeben kann, aber ich bin nicht in der Lage.

Es würde ein abgeleitetes Objekt von Tiere zu schaffen, die ein Argument und in der Lage ist, nimmt den Aufruf Anwendung verwenden

object TheDog(name: String) extends Animal { 

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

nicht sicher, wie implizit nennen Animal.apply für TheDog Objekt, wo ich passieren konnte ein Parameter (Name)
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 
//... 
} 

Antwort

2

Ab *Wrong top statement declaration* (ich nur diese verstehen können Teil Ihrer Frage) - Sie können nicht Konstruktor in bezwecken als object ein Singleton ist, so dass Sie einen Fall Klasse (ADT) verwenden sollte:

final case class TheDog(name: String) extends Animal 

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

val und Begleitobjekt mit apply wird automatisch für Fallklassen hinzugefügt Sie müssen also apply in Animal nicht selbst definieren. case class TheDog(val name: String) ist das gleiche wie .

ich die Nutzung auch trait s statt abstrakten Klasse:

trait Animal { 

    val name: String 

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

} 

Ich verstehe nicht, Ihre TypeClass Typ, aber wenn Sie wirklich Typklassen wollen:

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" 

Über Aufruf apply "implizit", ich weiß nicht, warum jemand das brauchen würde, aber:

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") 

Natürlich haben Sie createDog bieten und es sichtbar für einen Kunden zu machen, aber es ist nicht wirklich sinnvoll, wenn Sie nur ADTs verwenden können und definieren zusätzliche erforderliche apply s in Begleitobjekt:

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

    TheMouse(true) 

Wenn Sie einige Parameter Konstruktor hinzufügen möchten, fügen Sie einfach es:

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") 

Sie können sogar eine Fabrik für Fabrik erstellen (ich würde nicht empfehlen - diese Lö

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

Dank für die tiefe Erklärung: tion sieht schon kompliziert): oder einfach nur in einem Wrapper

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")' 

Aber noch was ist der Punkt, wenn man nur clazz entweder als Mitglied zugrunde liegenden bieten könnte. –

Verwandte Themen