Domanda

Oggi ho letto un libro e l'autore ha scritto che in una classe ben progettato l'unico modo per accedere agli attributi è attraverso uno di quei metodi di classe. E 'un pensiero ampiamente accettato? Perché è così importante per incapsulare gli attributi? Quali potrebbero essere le conseguenze di non farlo? Ho letto da qualche parte in precedenza che questo migliora la sicurezza o qualcosa di simile. Qualsiasi esempio in PHP o Java sarebbe molto utile.

È stato utile?

Soluzione

  

E 'un pensiero ampiamente accettato?

Nel mondo orientato agli oggetti, sì.

  

Perché è così importante per incapsulare gli attributi? Quali potrebbero essere le conseguenze di non farlo?

oggetti sono destinati ad essere entità coesive contenenti dati e comportamenti che altri oggetti possono accedere in modo controllato attraverso un'interfaccia pubblica. Se una classe non incapsulare i propri dati e il comportamento, non ha più controllo sui dati a cui si accede e non possono adempiere i suoi contratti con altri oggetti impliciti l'interfaccia pubblica.

Uno dei grossi problemi con questo è che se una classe deve cambiare internamente, l'interfaccia pubblica non dovrebbe avere al cambiamento. In questo modo non si rompe alcun codice e le altre classi possono continuare ad usarlo come prima.

  

Ogni esempio in PHP o Java sarebbe molto utile.

Ecco un esempio Java:

public class MyClass {
    // Should not be < 0
    public int importantValue;
    ...
    public void setImportantValue(int newValue) {
        if (newValue < 0) {
           throw new IllegalArgumentException("value cannot be < 0");
        }
    }
    ...
}

Il problema qui è che perché non ho incapsulato importantValue rendendola private piuttosto che pubblica, chiunque può venire avanti e aggirare il check-ho messo nel setter per evitare che l'oggetto di avere uno stato non valido. importantValue non dovrebbe mai essere inferiore a 0, ma la mancanza di incapsulamento rende impossibile per evitare che essere così.

Altri suggerimenti

  

Quali potrebbero essere le conseguenze di non   farlo?

L'intera idea alla base di incapsulamento è che tutta la conoscenza di tutto ciò che riguarda la classe (diversa la sua interfaccia) è all'interno della classe stessa. Ad esempio, che consente l'accesso diretto agli attributi pone l'onere di fare in modo eventuali assegnazioni sono valide sul codice di fare l'assegnazione. Se la definizione di ciò che è modifiche valide, si deve passare attraverso e audit tutto utilizzando la classe per assicurarsi che conformarsi. L'incapsulamento la regola in un mezzo metodo "setter" Basta cambiarlo in un unico luogo, e qualsiasi chiamante cercando qualcosa di divertente è possibile ottenere un'eccezione gettata a esso in cambio. Ci sono un sacco di altre cose che si potrebbe desiderare di fare quando un attributo cambia, e un setter è il posto giusto per farlo.

Se o non permettere l'accesso diretto per gli attributi che non hanno alcuna regola di legare loro (per esempio, tutto ciò che si inserisce in un numero intero va bene) è buona norma è discutibile. Suppongo che l'utilizzo di getter e setter è una buona idea per motivi di coerenza, vale a dire, sai sempre che è possibile chiamare setFoo() per modificare l'attributo foo senza dover guardare in alto se non è possibile farlo direttamente. Essi permettono anche di prova di futuro la classe in modo che se si dispone di codice aggiuntivo per l'esecuzione, il posto giusto per metterla è già lì.

Personalmente, penso che dover utilizzare getter e setter è goffo-guardare. Avevo x.foo = 34 di gran lunga scrittura di x.setFoo(34) e attendo con ansia il giorno in cui una lingua si presenta con l'equivalente di trigger del database per i membri che permettono di definire il codice che viene generato prima, dopo o al posto di un incarichi.

Opinioni su come si ottiene "buona OOD" sono dime una dozzina, e programmatori e designer anche molto esperti tendono a non essere d'accordo sulle scelte progettuali e le filosofie. Questo potrebbe essere un antipasto fiamma guerra, se si chiede alle persone in una vasta varietà di sfondo linguaggio e paradigmi.

E sì, in teoria sono teoria e pratica la stessa, quindi la scelta della lingua non dovrebbe influenzare il design di alto livello molto. Ma in pratica lo fanno, e buone e cattive cose accadono a causa di questo.

Fammi aggiungi a: Dipende. Encapsulation (in un linguaggio di supporto) si dà un certo controllo su come classi sono utilizzate, in modo da possono dire alla gente: questo è l'API, e si deve utilizzare questo. In altre lingue (ad esempio Python) la differenza tra API ufficiali e informali (soggetto a variazioni) interfacce è per convenzione di denominazione solo ( dopo tutto, siamo tutti adulti consenzienti qui )

L'incapsulamento non è una caratteristica di sicurezza.

Un altro pensiero a riflettere

L'incapsulamento con funzioni di accesso fornisce anche molto meglio manutenibilità in futuro. In risposta di Feanor sopra, funziona benissimo per applicare controlli di sicurezza (supponendo che l'instvar è privata), ma può avere benifits molto di più vasta portata.

Si consideri il seguente scenario:
1) aver completato la vostra applicazione, e distribuirlo a un insieme di utenti (interni, esterni, a prescindere).
2) BigCustomerA si avvicina alla vostra squadra e vuole un audit trail aggiunto al prodotto.

Se tutti utilizzano i metodi di accesso nel loro codice, questo diventa quasi banale da implementare. Qualcosa in questo modo:

MyApi Versione 1.0

public class MyClass {
    private int importantValue;
    ...
    public void setImportantValue(int newValue) {
        if (newValue < 0) {
           throw new IllegalArgumentException("value cannot be < 0");
        }
        importantValue = newValue;
    }
    ...
}


V1.1 MyApi (ora con audit trail)

public class MyClass {
    private int importantValue;
    ...
    public void setImportantValue(int newValue) {
        if (newValue < 0) {
           throw new IllegalArgumentException("value cannot be < 0");
        }
        this.addAuditTrail("importantValue", importantValue, newValue);
        importantValue = newValue;
    }
    ...
}

Gli utenti esistenti di API non apportare alcuna modifica alla loro codice e la nuova funzione (audit trail) è ora disponibile.
Senza di incapsulamento che utilizzano funzioni di accesso vostra fronte ad un grande sforzo di migrazione.


Quando si codifica per la prima volta, vi sembrerà un sacco di lavoro. La sua molto più veloce di tipo:. class.varName = something vs class.setVarName(something); ma se ognuno ha preso la via più facile, essere pagati per richiesta di funzionalità di BigCustomerA sarebbe un grande sforzo

Oggetto Oriente Programmazione esiste un principio che è noto come (http://en.wikipedia.org/wiki/Open/closed_principle): POC -> Principio di aperto e chiuso . Questo principio soggiorni per: un design di classe e dovrebbero essere aperte per l'estensibilità (eredità), ma chiuso per la modifica dei membri interni (incapsulamento) . Vuol dire che non si poteva essere in grado di modificare lo stato di un oggetto senza prendersi cura su di esso.

Quindi, nuovi linguaggi modificano solo le variabili interne (campi) attraverso le proprietà (getter e setter metodi in C ++ o Java). In C # proprietà compilazione di metodi in MSIL.

C #:

int _myproperty = 0;
public int MyProperty
{
    get { return _myproperty; }
    set { if (_someVarieble = someConstantValue) { _myproperty = value; } else { _myproperty = _someOtherValue; }  }    
}

C ++ / Java:

int _myproperty = 0;
public void setMyProperty(int value) 
{
  if (value = someConstantValue) { _myproperty = value; } else { _myproperty = _someOtherValue; }
}
public int getMyProperty() 
{
    return _myproperty;
}

Prendere tesi idee (da Head First C # ):

  • pensare a modi i campi possono abusato. Che cosa può andare male se non sono impostati correttamente.
  • E 'tutto nella tua classe pubblico? Passa un po 'tempo a pensare circa l'incapsulamento.
  • Quali campi richiedono l'elaborazione o il calcolo? Essi sono i primi candidati.
  • Solo rendere campi e metodi pubblici, se è necessario. Se non si dispone di un motivo per dichiarare qualcosa di pubblico, non lo fanno.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top