2015-07-21 8 views
8

ho visto un po 'di codice da una libreria:Perchè classe scala bisogno di estendere esplicitamente AnyRef

trait A extends scala.AnyRef 
trait B extends scala.AnyRef with A 

Perché A bisogno di estendere esplicitamente AnyRef? Non tutte le classi sono implicitamente derivate da AnyRef?

Perché B è necessario estendere AnyRef anche se lo ha già fatto A? Qual è la differenza per modificare sopra il codice in:

trait A 
trait B extends A 
+2

Che libreria è? –

+0

una libreria ben nota. non voglio menzionare il nome qui. – jiangok

+4

Perché no? Alcuni contesti potrebbero aiutare a capire se c'è qualche ragione. –

risposta

7

Direi che non c'è alcuna differenza.

Dalle scala documentation

classi definite dall'utente definiscono i tipi di riferimento di default; cioè sempre sottoclasse (indirettamente) scala.AnyRef.

Per dimostrare ulteriormente il punto

scala> trait A 
defined trait A 

scala> trait B extends A 
defined trait B 

scala> val a = new A { } 
a: A = [email protected] 

scala> val b = new B { } 
b: B = [email protected] 

scala> a.isInstanceOf[AnyRef] 
res4: Boolean = true 

scala> b.isInstanceOf[AnyRef] 
res7: Boolean = true 
2

Non è necessario estendere in modo esplicito AnyRef. AnyRef è l'equivalente dell'oggetto Java in Scala. Creando un'istanza di una classe, quell'istanza estenderà AnyRef implicitamente indipendentemente dal fatto che sia stata esplicitamente citata in una delle sue super classi o meno.

Il codice seguente crea solo una classe anonima, in tal modo si estende anche AnyRef implicitamente:

trait A 
val a = new A { } 

Ecco la spiegazione da scala-lang.org:

La superclasse di tutti classes scala.Any ha due sottoclassi dirette scala.AnyVal e scala.AnyRef che rappresentano due diversi mondi di classe: classi di valore e classi di riferimento. Tutte le classi di valore sono predefinite; corrispondono ai tipi primitivi di lingue simili a Java. Tutte le altre classi definiscono i tipi di riferimento. Le classi definite dall'utente definiscono i tipi di riferimento per impostazione predefinita; cioè sempre (indirettamente) sottoclasse scala.AnyRef. Ogni classe definita dall'utente in Scala estende implicitamente il tratto scala.ScalaObject. Le classi dall'infrastruttura su cui è in esecuzione Scala (ad esempio l'ambiente di runtime Java) non estendono scala.ScalaObject. Se Scala viene utilizzato nel contesto di un ambiente di runtime Java, scala.AnyRef corrisponde a java.lang.Object. Si noti che il diagramma sopra mostra anche conversioni implicite chiamate viste tra le classi di valore. Ecco un esempio che dimostra che entrambi i numeri, caratteri, valori booleani e le funzioni sono oggetti, proprio come ogni altro oggetto:

http://docs.scala-lang.org/tutorials/tour/unified-types.html

Dal Scala 2.10 è anche possibile estendere AnyVal. Da scala-lang.org:

AnyVal è la classe radice di tutti i tipi di valore, che descrivono valori non implementati come oggetti nel sistema host sottostante. Prima di Scala 2.10, AnyVal era un tratto sigillato. A partire da Scala 2.10, tuttavia, è possibile definire una sottoclasse di AnyVal denominata classe di valore definita dall'utente che viene elaborata appositamente dal compilatore.Le classi di valore utente definite correttamente forniscono un modo per migliorare le prestazioni sui tipi definiti dall'utente evitando l'allocazione di oggetti in fase di runtime e sostituendo le chiamate di metodi virtuali con invocazioni di metodi statici.

+0

Potrebbe valere la pena di aggiungere informazioni su 'AnyVal' aggiunto in seguito, il che rende la parte" loro sempre ... sottoclasse scala.AnyRef "non esattamente vera. – Suma

+0

Controllando con isInstanceOf vedrai che le classi create dall'utente che estendono AnyVal in realtà estendono anche AnyRef. È strano ma è così che è stato implementato. –

+0

Non è esattamente vero. Accade semplicemente che 'isInstanceOf' si basi interamente sul tipo di runtime jvm e, in quanto tale, trapelhi informazioni che rappresentano praticamente un dettaglio di implementazione. Quando chiamate 'isInstanceOf' su qualche istanza di classe value, il valore viene prima inserito in una scatola, e naturalmente questa istanza boxed estende' Object' (aka 'AnyRef'). Puoi chiamarlo bug, comportamento sorprendente o caso evidente di [astrazione leaky] (https://en.wikipedia.org/wiki/Leaky_abstraction). Ma non si può dire che "AnyVal" sia un "AnyRef". –

Problemi correlati