2016-01-22 24 views
13

Il seguente codice non può essere compilato:Scala conversione implicita da genitore tratto

import scala.language.implicitConversions 

trait Base { 
    class Wrp[+T](val v: T) // wrapper/internal representation 
} 

trait BooleanOps extends Base { 
    // implicit conversion 
    implicit def lift2BooleanOpsCls(x: Boolean): BooleanOpsCls = 
    new BooleanOpsCls(new Wrp[Boolean](x)) 
    class BooleanOpsCls(wx: Wrp[Boolean]) { 
    def ||(wy: =>Wrp[Boolean]): Wrp[Boolean] = new Wrp[Boolean](wx.v || wy.v) 
    } 
} 

trait MyExample extends BooleanOps { 
    // test method 
    def foo(): Wrp[Boolean] = { 
    val ret: Wrp[Boolean] = false || new Wrp[Boolean](true) 
    ret 
    } 
} 

uscita:

MyExample.scala:18: error: type mismatch; 
found : MyExample.this.Wrp[Boolean] 
required: Boolean 
     val ret: Wrp[Boolean] = false || new Wrp[Boolean](true) 
             ^

Ma se io:

1) messo la class Wrp al di fuori di Base

o

2) spostare il corpo di BooleanOps a MyExample

tutto compila.

Perché l'esempio originale non funziona? Se hai qualche idea in questo comportamento, l'aiuto sarebbe apprezzato. Grazie.

risposta

1

L'esempio originale funzionerà se si rinomina il metodo ||. Il compilatore trova il metodo false.||() e non si preoccupa di cercare un implicito che potrebbe funzionare anche lì.

+0

In effetti, questo funziona, ma sto cercando di sovraccaricare il comportamento dell'operatore '||'. Il compilatore trova il metodo con lo stesso nome ('||'), ma il tipo di argomento è diverso ('Wrp [Boolean]' invece di 'Boolean'), quindi dovrebbe eseguire la ricerca implicita. Questo accade davvero se metto la conversione implicita nel corpo di 'MyExample' o se inserisco la definizione' class Wrp' al di fuori di 'Base', come specificato nella domanda. Non capisco perché queste soluzioni funzionino e l'esempio originale no. – perovic

5

Un problema è la natura chiamata per nome dell'argomento nella def ||(wy: =>Wrp[Boolean])
se rewite per def ||(wy: Wrp[Boolean]) funziona

ma sono d'accordo che è strano che funziona se si sposta in giro WRP o BooleanOpsCls! Inteso o bug di risoluzione implicita ??

+0

Ottimo, posso confermare che funziona. Grazie :) Rimane la domanda che cosa sta esattamente accadendo nell'esempio originale, anche in relazione ai due workaround proposti. – perovic

+1

@perovic Solo l'idea nel contesto della risposta @cbastin: presumo che, a causa della natura dell'argomento call-by-name, la ricerca implicita avvenga in modo diverso, poiché '=> Wrp [Boolean]' è un blocco di codice piuttosto che un tipo . A causa di questo, il compilatore non considera questa definizione del metodo applicabile durante la ricerca implicita. Sfortunatamente non posso confermarlo con alcuna fonte affidabile, quindi è un'ipotesi completamente selvaggia. Ma dato che il comportamento è strano e dipende dal posizionamento di 'Wrp', sembra un bug, e credo che valga la pena pubblicarlo come un biglietto jira per il team del compilatore? – Archeg

+0

@Archeg Grazie per il consiglio. Sembra che molti elementi e regole stiano interagendo. Non sono ancora sicuro che questo sia un bug, quindi aspetterò un po 'di più nella speranza che qualcuno sia in grado di dare una spiegazione completa. – perovic

1

Il problema è che non esiste un unico classe chiamata Wrp (ignorare il T per un attimo) - Base non definisce Wrp ma definisce un nome sottoclasse di ogni concreta classe che estende Base. Anche gli impliciti sono un'aringa rossa. L'errore che è il regalo è la menzione di MyExample.this.Wrp - ricorda che non esiste tale classe anche come MyExample - val x = new MyExample avrebbe tipo Object with MyExample.

+0

Grazie per la risposta Rob.Nel codice attuale 'Wrp' è un tipo astratto, l'ho semplificato qui. Ma l'esempio funziona ancora se l'argomento 'Wrp [Boolean]' dell'operatore '||' è call-by-value o se inserisco la conversione implicita (sia 'implicit def' che' class') all'interno di MyExample . Sai come si riferisce alla tua risposta? – perovic

+0

Non sono sicuro ... forse potresti aggiungere un esempio minimo aggiuntivo alternativo? –

Problemi correlati