2014-05-19 12 views
6

Capisco il solito problema "Attività non serializzabile" che si verifica quando si accede a un campo oa un metodo che non rientra nell'ambito di una chiusura.Evitare "Attività non serializzabile" con metodo nidificato in una classe

Per risolvere il problema, di solito definiscono una copia locale di questi campi/metodi, che evita la necessità di serializzare l'intera classe:

class MyClass(val myField: Any) { 
    def run() = { 
    val f = sc.textFile("hdfs://xxx.xxx.xxx.xxx/file.csv") 

    val myField = this.myField 
    println(f.map(_ + myField).count) 
    } 
} 

Ora, se io definisco una funzione annidata nel metodo run, essa non può essere serializzato:

class MyClass() { 
    def run() = { 
    val f = sc.textFile("hdfs://xxx.xxx.xxx.xxx/file.csv") 

    def mapFn(line: String) = line.split(";") 

    val myField = this.myField 
    println(f.map(mapFn(_)).count) 

    } 
} 

non capisco perché ho pensato "mapFn" sarebbe di portata ... Ancora più strano, se mi definisco mapFn di essere un val invece di una definizione, allora funziona :

class MyClass() { 
    def run() = { 
    val f = sc.textFile("hdfs://xxx.xxx.xxx.xxx/file.csv") 

    val mapFn = (line: String) => line.split(";") 

    println(f.map(mapFn(_)).count)  
    } 
} 

È correlato al modo in cui Scala rappresenta le funzioni annidate?

Qual è il modo consigliato per gestire questo problema? Evita le funzioni annidate?

+0

Anche io sto vedendo questo, una volta che si cambia in Val non è defs funziona! Quindi grazie per aver condiviso questa osservazione. – MahdeTo

risposta

1

Non funziona nel modo che nel primo caso f.map(mapFN(_)) equivale a f.map(new Function() { override def apply(...) = mapFN(...) }) e nel secondo è solo f.map(mapFN)? Quando dichiari un metodo con def, probabilmente è solo un metodo in qualche classe anonima con il riferimento implicito $outer alla classe che lo include. Ma lo map richiede un Function, quindi il compilatore deve completarlo. Nel wrapper ti riferisci solo ad un metodo di quella classe anonima, ma non all'istanza stessa. Se si utilizza val, si ha un riferimento diretto alla funzione passata allo map. Non ne sono sicuro, sto solo pensando ad alta voce ...

Problemi correlati