2016-04-05 31 views
6

Sto cercando di aggiungere nuove funzioni a tipi esistenti (così posso fare in modo che l'IDE suggerisca funzioni rilevanti per tipi di cui non ho il controllo, ad esempio Future[Option[A]]). Ho esplorato sia le classi implicite che le conversioni implicite per ottenere questo risultato ed entrambe sembrano offrire lo stesso comportamento.Classe implicita rispetto alla conversione implicita in tratto

C'è qualche differenza tra l'utilizzo efficace una classe implicita:

case class Foo(a: Int) 
implicit class EnrichedFoo(foo: Foo) { 
    def beep = "boop" 
} 
Foo(1).beep // "boop" 

E l'utilizzo di una conversione implicita:

case class Foo(a: Int) 
trait Enriched { 
    def beep: String 
} 
implicit def fooToEnriched(foo: Foo) = new Enriched { 
    def beep = "boop" 
} 
Foo(1).beep // "boop" 

Suppongo che una differenza qui potrebbe essere che il primo esempio crea un one fuori classe invece di un tratto, ma potrei facilmente adattare la classe implicita per estendere un tratto astratto, ad esempio:

case class Foo(a: Int) 
trait Enriched { 
    def beep: String 
} 
implicit class EnrichedFoo(foo: Foo) extends Enriched { 
    def beep = "boop" 
} 
Foo(1).beep // "boop" 

risposta

5

Per quanto ne so, sono praticamente identici. Le regole di scoping si applicano anche a entrambi.

A mio parere, utilizzerei lo implicit classes per il tipo di situazione. Probabilmente sono stati creati proprio per qualcosa di simile.

Le conversioni implicite, per me, sono più appropriate quando si dispone già di due diversi tipi di classi e si desidera effettuare la conversione tra i due.

è possibile controllare la proposta iniziale per le classi implicite right here. ci si dice:

Un nuovo costrutto del linguaggio si propone di semplificare la creazione di classi che forniscono metodi di estensione ad un altro tipo.

Si può anche vedere come è desugars implicit classes. Il seguente:

implicit class RichInt(n: Int) extends Ordered[Int] { 
    def min(m: Int): Int = if (n <= m) n else m 
    ... 
} 

sarà desugar in:

class RichInt(n: Int) extends Ordered[Int] { 
    def min(m: Int): Int = if (n <= m) n else m 
    ... 
} 
implicit final def RichInt(n: Int): RichInt = new RichInt(n) 
+1

Un'ulteriore cosa da ricordare è che, quando si desidera convertire implicitamente un oggetto di tipo A in un oggetto di tipo B, dove B è un * 'classe finale' *, un 'implicito def' è l'unica opzione. – Adowrath

0

Bene per me è una questione di preferenza. In realtà è stato creato il implicit classes per facilitare la creazione di classi che forniscono metodi di estensione ad un altro tipo. Le classi implicite aggiungono molto valore a value classes.