2015-11-20 49 views
6

Ho familiarità con Java, ma sto solo iniziando a imparare JavaFX e in particolare a conoscere le proprietà JavaFX. Capisco il modello di progettazione di base, come mostrato nel seguente esempio da Oracle:Quando utilizzare setter e getter di proprietà JavaFX, invece di utilizzare direttamente la proprietà

package propertydemo; 

import javafx.beans.property.DoubleProperty; 
import javafx.beans.property.SimpleDoubleProperty; 

class Bill { 

    // Define a variable to store the property 
    private DoubleProperty amountDue = new SimpleDoubleProperty(); 

    // Define a getter for the property's value 
    public final double getAmountDue(){return amountDue.get();} 

    // Define a setter for the property's value 
    public final void setAmountDue(double value){amountDue.set(value);} 

    // Define a getter for the property itself 
    public DoubleProperty amountDueProperty() {return amountDue;} 

} 

Quello che non capisco è quando/perché dovrei utilizzare i metodi getter e setter, invece di usare direttamente la struttura?

Quello che stavo pensando è che potresti volere qualche codice personalizzato nel getter e/o setter che possa fare una pre o post manipolazione/convalida dei dati, ma se crei un getter e/o setter personalizzato, tu otterrebbe risultati diversi quindi, a seconda se si utilizza direttamente il getter/setter o la proprietà, che per me sembra pericoloso.

Se il getter/setter chiama semplicemente i metodi get e set della proprietà, allora perché persino averli?

Qualsiasi comprensione di ciò sarebbe apprezzata.

+0

da [learn javafx ebook] (http://www.apress.com/9781484211434). 'Ulteriori getter e setter, utilizzando la convenzione di denominazione JavaBeans, vengono aggiunti per rendere la classe interoperabile con gli strumenti e i framework precedenti che utilizzano le convenzioni di denominazione JavaBeans precedenti per identificare le proprietà di una classe. ' – Kachna

+0

A mio parere, getter e setter aggiuntivi non sono richiesti. – Kachna

+0

@Kachna Sicuramente questo dipende dal tuo caso d'uso. Ad esempio, se si desidera utilizzare le proprietà JavaFX in un'entità JPA, è necessario utilizzare i metodi get e set. Allo stesso modo se stai usando il marshalling JSON o XML, ecc. –

risposta

11

Il modello di proprietà JavaFX è progettato per estendere il vecchio modello standard JavaBean. Quindi, nel tuo esempio, secondo la convenzione JavaBean, hai una proprietà (lettura-scrittura) di tipo double chiamata amount. Questo è determinato dai due metodi

public double getAmount() ; 
public void setAmount(double amount); 

Il modello JavaBean consente alcuni "osservabilità" limitata tramite "proprietà bound", in cui i fagioli supportano registrando un PropertyChangeListener. Un toolkit di interfaccia utente spesso ha bisogno di osservare le proprietà e rispondere ai cambiamenti. Ad esempio, ha senso che un Label abbia una proprietà text. Se la proprietà text cambia, è necessario ricevere la notifica Label, in modo che sappia ridisegnare se stessa. A prima vista, l'uso di JavaBeans con proprietà associate sarebbe un modo per farlo. Tuttavia, l'uso di questo meccanismo in un kit di strumenti dell'interfaccia utente produce problemi di prestazioni, perché non c'è modo di avere notifiche che un valore non è più valido senza calcolarlo immediatamente. Ciò significa, ad esempio, che il layout verrà ricalcolato su ogni singola modifica di una proprietà.

Quello che il team JavaFX apparentemente miravano a fare era definire un modello che

  1. conformata al modello JavaBean standard e
  2. supportato proprietà osservabili dove invalidazione potrebbe essere rintracciato senza ricalcolare valori dipendenti ogni volta che il valore modificato ("valori pigramente osservabili")

Quindi la soluzione è quella di creare JavaFX proprietà che supportano sia ChangeListener s, notificati quando cambia un valore, e InvalidationListener s, che vengono notificati quando un valore non è più valido. Ciò significa che, ad esempio, un meccanismo di layout può tracciare se è attualmente valido o meno senza forzare un ricalcalo quando diventa non valido. Il layout verrà ricalcolato solo su un effettivo impulso dello schermo (ad esempio quando la scena viene renderizzata) e solo se non è valida.

(Come concetto proof-of-rapido, considerare quanto segue:

DoubleProperty width = new SimpleDoubleProperty(3); 
DoubleProperty height = new SimpleDoubleProperty(4); 
ObservableDoubleValue area = Bindings.createDoubleBinding(() -> { 
    double a = width.get() * height.get(); 
    System.out.println("Computed area: "+a); 
    return a ; 
}, width, height); 
System.out.println("Area is "+area.getValue()); 
width.set(2); 
height.set(3); 
System.out.println("Area is "+area.getValue()); 

Nota qui che il valore intermedio, quando width è 2 e height è ancora 4, non viene mai calcolato.)

Quindi i valori in JavaFX sono rappresentati da questi osservabili Properties che supportano entrambi gli ascoltatori di invalidazione e cambiano gli ascoltatori, il che significa che sono sostanzialmente "pigramente osservabili". Esporre la proprietà stessa tramite un metodo di accesso proprietà (amountProperty() nell'esempio) è sufficiente per supportare questa funzionalità.

Semanticamente, tuttavia, esporre un DoubleProperty significa che il bean ha un valore di tipo double. Per mantenere la compatibilità con la vecchia convenzione JavaBean, questo bean dovrebbe pubblicizzare questo fatto esponendo i corrispondenti metodi get e set. Di conseguenza, il modello di proprietà JavaFX richiede sia un "accesso proprietà" (amountProperty()) che i metodi standard JavaBean (getAmount() e setAmount(...)). Ciò significa che i bean che seguono il pattern JavaFX possono essere utilizzati ovunque venga utilizzato il modello standard di JavaBean, ad esempio in JPA.

Nota che affinché il motivo funzioni correttamente, dovrebbe sempre essere vero che amountProperty().get() == getAmount() e che amountProperty().set(x) ha lo stesso effetto di setAmount(x). Questo è garantito (anche se la classe bean è sottoclasse) rendendo i metodi get e setfinal, come nell'esempio.

Se stai invocando i metodi tu stesso per recuperare o modificare il valore della proprietà, non importa quale chiami, poiché è garantito che abbiano lo stesso effetto. Dal momento che il modello di proprietà JavaFX è un'estensione del modello JavaBean, potrebbe essere preferibile chiamare i metodi get e set: in un certo senso, l'accesso al valore richiede solo la funzionalità JavaBean, non la funzionalità completa della proprietà JavaFX, quindi potrebbe dare un senso semantico a fare affidamento solo su tale funzionalità. In pratica, tuttavia, non fa differenza quale uso.

+1

Grazie per la tua spiegazione dettagliata. cosa circa il caso in cui il setter manipola effettivamente i dati, per esempio se si dispone di uno StringProperty firstName: 'firstName.set (name.trim())' In questo caso si chiama il metodo setter è diverso da chiamare 'set()' sulla proprietà, o è un no-no con Proprietà JavaFX. – vewert

+0

Spiacente, volevo aggiungere un esempio più dettagliato, ma sembra che non sia possibile aggiungere blocchi di codice ai commenti. – vewert

+1

Si spezzerebbe più convenzioni con quell'esempio. Come accennato, nel modello di proprietà JavaFX dovresti garantire che 'setFirstName (x)' è equivalente a 'firstNameProperty(). Set (x)'. Ma nel normale schema di Java Bean, dovresti davvero garantire che 'setFirstName (x); getFirstName() 'restituisce' x', assumendo che non si verifichino altre operazioni sull'oggetto tra le due chiamate di metodo. Se si voleva veramente fare qualcosa del genere, sottoclasse 'StringPropertyBase' e ​​sovrascrivere' setString (...) 'e' setValue (String) '. –