Il passaggio di questo argomento come argomento può potenzialmente causare l'esposizione di stato dell'oggetto non valido?

1

Questa domanda si basa su due premesse:

  • Primo: un oggetto deve sempre avere uno stato valido. È discusso anche in vari post. link
  • Secondo: una classe può affidarsi esclusivamente a se stessa per anticipare se le sue istanze avranno uno stato valido.

Ci sono alcune conseguenze a questo tipo: non utilizzare proprietà pubbliche o protette. È semplice capire perché dovrebbero essere evitati. Esistono post anche su questo argomento specifico. Perché il codice Clean suggerisce di evitare le variabili protette?

Un'altra conseguenza è che il riferimento this non dovrebbe essere dato a metodi di altre classi: link Almeno, si consiglia spesso di non farlo nei costruttori.

Tuttavia, in senso stretto, questo non proibirebbe quasi ogni istanza di passare this ai metodi di qualsiasi dipendenza? Dopotutto, a meno che una classe non faccia parte di una gerarchia di classi, come può evitare che un oggetto abbia uno stato non valido quando passa this ?

Un esempio in PHP:

class ClientCodeClass {
    public function carryOutTask(ParentClass $object) {
        // Client code now has access to the object in illegal state and things may mishappen because of that.
    }
}

class ParentClass {
    private $client_code_class;

    public function __construct(ClientCodeClass $client_code_class) {
        $this->client_code_class = $client_code_class;
    }

    protected function exposeParentClass() {
        // At this time, $this is in invalid state, and we're passing it to client code!
        $this->client_code_class->carryOutTask($this);
    }
}

class ChildClass extends ParentClass {
    public function doSomething() {
        $this->setIllegalState();
        $this->exposeParentClass();
        $this->setLegalState();
    }
}

$child_class = new ChildClass();
$child_class->doSomething();

Quindi la mia domanda è: è vero che le mie due premesse sono corrette e che verrebbero violate se una classe (a meno che non estenda un'altra classe e sia marcata final ) passi this a un metodo di un'altra obiettare?

Domanda successiva: questo non limita drasticamente l'uso consentito dei callback? Dopotutto, quando un oggetto richiama la richiamata, non può garantire che sia valida - mentre quella callback potrebbe funzionare su quello stesso oggetto.

    
posta user2180613 15.07.2016 - 09:12
fonte

1 risposta

1

I tuoi locali sono corretti. Tuttavia, ciò che può essere considerato come uno stato "valido" è molto soggettivo. Di solito significa che le ipotesi che lo scrittore della classe ha sulla struttura dei dati contenuti all'interno di istanze di quella classe sono corrette.

L'unico modo per sapere che queste premesse non sono invalidate dal codice in un'altra posizione, è quello di garantire che tutte le modifiche alle istanze della classe avvengano tramite un'API pubblica fornita dalla classe. Se disponi di tale API pubblica, significa che tutte le modifiche apportate ai dati delle tue istanze sono convalidate dalla classe che hai scritto. Ciò significa che (se il codice nella definizione della classe non contiene errori) non è possibile invalidare lo stato delle istanze.

Questo è esattamente il motivo per cui esistono metodi accessor (getter / setter) e anche perché esiste la separazione tra metodi pubblici e privati.

TL; DR:

Non c'è niente di sbagliato nel passare this ad altro codice, a patto che le classi / metodi lo si passino per manipolare l'istanza della classe usando la sua API pubblica, poiché ciò significa che la classe / istanza stessa ha l'ultima parola sulla modifiche che potrebbero accadergli.

Inoltre, quando passi this ad altro codice prima la tua classe ha finito di rendere valido il suo stato, è davvero possibile che altri metodi della classe vengano chiamati prima di costruire il codice valido stato era finito. Ecco perché usare this all'interno del costruttore è una cattiva idea.

Quando si ha a che fare con l'ereditarietà, è compito dell'implementatore delle classi figlie non violare le assunzioni fatte per le istanze delle classi genitore. Questo è davvero qualcosa che può accadere, ma non è la preoccupazione della classe genitore a garantire che le sue classi figlie siano corrette.

Per quanto riguarda la domanda di follow-up sui callback: dovresti registrare un callback solo a qualcosa dopo il suo stato è valido. Altrimenti, in effetti, si introduce una condizione di competizione in cui il callback potrebbe essere attivato prima che l'oggetto sia pienamente valido. Questo in effetti limita i luoghi in cui sono consentiti i callback. Oppure, in alternativa, quali informazioni è possibile ammettere che un determinato callback sia valido sulla tua istanza.

    
risposta data 17.07.2016 - 12:03
fonte

Leggi altre domande sui tag