2011-09-17 11 views
9

PHP introduces a method that allows you to pick out all public values of an instance. C'è un modo per farlo in Scala? Vale a recuperare tutti i valori di tutti i campi pubblici di una classe istanziata (non oggetto).Come ottenere campi pubblici (ei rispettivi valori) di un'istanza in Scala/Java

diamo noi assumere Ho questa classe

class TestElement(datatype: Datatype, var subject: String, var day: Int, var time: Int) 
    extends DataElement(datatype: Datatype) {  
    def to(group: Group) = group.add(this); 
} 

var element = new TestElement(datatype, "subject", 1, 1); 

Quello che mi serve dal metodo in oggetto, è quello di ottenere una mappa o di due collezioni di valori.

var element.method          // the function I need 
ret: (("subject", "subject"), ("day", 1), ("time", 1)) // its output 

risposta

20

E 'il momento per andare a letto, in modo da non avere il tempo per una risposta completa, ma a guardare i risultati di element.getClass.getFields (o getDeclaredFields per i campi privati) - è possibile chiamare getValue(element) sulle Field oggetti per andare a prendere i loro valori.


desti, e ancora nessuna risposta migliore, quindi:

In primo luogo, si noti che in termini di Java, la classe non ha un campo di soggetto pubblico, cosa che ha è un campo privato e soggetto metodi accessor subject() e subject_ $ eq (String).

È possibile scorrere i oggetti campo privati ​​come descritto sopra, popolando una mappa dalle coppie:

def getFields(o: Any): Map[String, Any] = { 
    val fieldsAsPairs = for (field <- o.getClass.getDeclaredFields) yield { 
    field.setAccessible(true) 
    (field.getName, field.get(o)) 
    } 
    Map(fieldsAsPairs :_*) 
} 

'quindi possibile definire questo metodo su TestElement (sostituendo o con this), o più in generale utilmente definire una conversione in modo che si può chiamare getFields su qualsiasi riferimento

implicit def any2FieldValues[A](o: A) = new AnyRef { 
    def fieldValues = getFields(o) 
} 

in modo che

element.fieldValues 

darà il risultato desiderato.

+0

eccellente, grazie mille – sdkfasldf

+0

Cosa fa la sintassi ': _ *'? –

2

Si può fare qualcosa relativamente vicino a questo per classi case:

case class SomeEntity(name : String, value : Int, misc : Boolean) 
val s = SomeEntity("Tom", 42, false) 
println(s.productIterator.map(_.toString).mkString(", ")) // "Tom, 42, false" 

... come ci si aspetterebbe, itera productIterator oltre gli elementi di tipo qualsiasi. Questo metodo viene generato automaticamente solo per le classi di casi e non verrà recuperato il nome del campo. Per qualcosa di più, dovrai usare la riflessione e, per questo, potresti voler aspettare la 2.10 per uscire.

+0

Cosa cambia in 2.10? – sdkfasldf

3

A per la risposta di Philippe, è possibile farlo per le classi del caso.

Più in generale, la stessa tecnica funziona per qualsiasi sottoclasse di Product. Oltre alle classi di casi, le tuple sono un altro ovvio esempio, ma la lista è molto più ampia di quella.

Date un'occhiata al "sottoclassi noti", qui: http://www.scala-lang.org/api/current/scala/Product.html

1

Solo una nota per quelli che cercano di migliorare questo facendo @duncan s' di tipo forte approccio:

invece di restituire un Map[String, Any], dove il valore è tipizzata come qualsiasi, si poteva fare seguente:

def propertiesAsPairs() = { 
    val fields = (this.getClass.getDeclaredFields()) 
    for (field <- fields) yield { 
     field.setAccessible(true); 
     (field.getName, field.get(this)); 
    } 
} 
+0

Qual è il tipo di ritorno di questo? Mi sembra come Array [Pair [String, Any]], che non ti ha comprato nulla? –

0

Scala rende volutamente val, var e def parti un'interfaccia comune, in modo da poter repl asso i primi due con il secondo senza rompere alcun codice - senza nemmeno richiedere una ricompilazione.

Quindi, mentre è possibile fare ciò che si vuole, risulterebbe in un codice fragile, che fa il genere di cose che non dovrebbe fare.

+0

Penso che direi che per le classi di dati come questo, il punto è semplicemente il trasferimento di valori nei campi. –

+0

anche se mi hai chiesto di chiedere a http://stackoverflow.com/q/7477248/97777 –

Problemi correlati