2016-12-24 5 views
1

Ich versuche zu verstehen "untere Grenze" in Scala. Hier finden Sie das folgende Beispiel"Untergrenze" in Scala Verständnis

class Animal 
class Dog extends Animal 
class Puppy extends Dog 
class Human extends Animal 
class Plant 
class AnimalDisplay{ 
    def displayUptoDog [T >: Dog](t: T){ 
    println(t) 
    } 

    def displayUptoAnimal [T >: Animal](t: T){ 
    println(">>"+t.getClass()) 
    } 

} 

object ScalaLowerBoundsTest { 
    def main(args: Array[String]) {  
    val animal = new Animal 
    val dog = new Dog 
    val puppy = new Puppy 
    val human=new Human 
    val plant = new Plant 
    val animalDisplay = new AnimalDisplay 

    println("Upto Animal") 
    animalDisplay.displayUptoAnimal(animal) 
    animalDisplay.displayUptoAnimal(dog) 
    animalDisplay.displayUptoAnimal(puppy) 
    animalDisplay.displayUptoAnimal(human) 
    animalDisplay.displayUptoAnimal(plant) 

println("Upto Dog") 
    animalDisplay.displayUptoDog(animal)  
    animalDisplay.displayUptoDog(dog) 
    animalDisplay.displayUptoDog(puppy) 
// prints: [email protected] 
    animalDisplay.displayUptoDog(human) 
//print:[email protected] 
    animalDisplay.displayUptoDog(plant) 
//prints:[email protected] 
    } 
} 

Meine Fragen

  1. sind als Welpe nicht ein Hund ist und nicht eine Superklasse von Hund, dann warum animalDisplay.displayUptoDog(puppy) erlaubt? einige echte usecase wird mir helfen, besser zu verstehen,

  2. Wenn es (animalDisplay.displayUptoDog(puppy)) erlaubt es dann sollte Druck [email protected] statt [email protected]

  3. animalDisplay.displayUptoDog (human), wo Mensch nicht eine Superklasse ist von Hund warum ist es dann erlaubt und Druck „[email protected]
  4. animalDisplay.displayUptoDog (Pflanze), wo Pflanze nicht in der gleichen Hierarchie ist, t hen, warum es auch und „[email protected]
  5. Druck erlaubt ist

Lassen Sie mich wissen, ob ich irgendeine Sache ist

+1

'com.typeSystem.typeBound.lowerBound.Puppy' ist die Laufzeitklasse. Es sagt nichts über den Typ der Kompilierzeit aus. Sie können einen 'TypeTag' verwenden, um Informationen zum Kompilierungszeittyp zu erhalten. –

Antwort

0

animalDisplay.displayUptoDog(puppy) erlaubt bin fehlt, weil Sie Puppy werfen können zu einem Dog, wie folgt aus:

animalDisplay.displayUptoDog(puppy: Dog) 

Jetzt können Sie fragen, was ist der Punkt, der untere Schranken für T in Methodensignaturen verwenden, einfach, wenn Sie es, das Objekt zu T upCast kann so f es ist? Um diese Frage zu beantworten, denke ich, dass es am besten ist, ein Beispiel zu betrachten, wo untere Grenzen tatsächlich nützlich oder sogar notwendig sind.

Ein sehr häufiger Anwendungsfall für die untere Grenze ist, wenn Sie, dass einige Verfahren einen Wert des Typs, um sicherzustellen, möchten zurückzugibt, die mit einem anderen Typ, zum Beispiel in Option[A] gemeinsam ist, ist es eine Methode:

def getOrElse[B >: A](default: ⇒ B): B 

Wenn wir möchten, dass es der Typ ist, der für A und B üblich ist, ist die einzige sinnvolle Option, wenn A ein Subtyp von B ist. Im umgekehrten Fall (B <: A) konnten Sie A nicht zurückgeben, wenn diese Option Some[A] war, da A kein Untertyp von B ist. Hier

ist ein Beispiel, wie es funktioniert, wenn wir es auf die Dog Klassenhierarchie gelten:

val d1 = Some(dog).getOrElse(puppy) 
d1: Dog = [email protected] 

val d2 = (None: Option[Dog]).getOrElse(puppy) 
d2: Dog = [email protected] 

val d3 = Some(puppy).getOrElse(dog) 
d3: Dog = [email protected] 

val d4 = (None: Option[Puppy]).getOrElse(dog) 
d4: Dog = [email protected] 

Wie Sie in allen Fällen sehen sie wie erwartet verhält. Rufen getOrElse, wenn A und B sind entweder Dog oder Puppy gibt immer einen Typ, der für beide von ihnen ist, die Dog ist.

Verwandte Themen