In alcuni contesti di IOC, potrebbe essere richiesto il costruttore di un oggetto immutabile polimorfico nella sua interfaccia?

1

Generalmente, i costruttori in un'interfaccia sono considerati come anti-pattern. Alcune lingue nemmeno lo consentono.

Quindi non capisco come dovremmo trattare con oggetti immutabili polimorfici in alcuni particolari contesti di IOC ...

Diciamo che dobbiamo istanziare un oggetto polimorfico, la sua classe che implementa la nostra interfaccia è implementata e fornita dal client.
 Come scenario stupido ma semplice, diciamo che questo oggetto è un oggetto valore e come tale dovrebbe essere immutabile, il che significa che lo stato dell'oggetto dovrebbe essere valido dal momento in cui viene istanziato ...

Il nostro codice:

// A user class implementing our interface...
$immutablePolymorphe = $userConfig['immutable_polymorphe_class'];

// Here we must know what to inject to its constructor...
$immutablePolymorphe = new $immutablePolymorphe($state);

// Then do something with that polymorphe...

Quindi non dobbiamo costringere qui il costruttore, quindi l'interfaccia? Mi manca qualcosa?

    
posta user285001 29.11.2018 - 22:20
fonte

2 risposte

2

In un contesto OOP, avere un costruttore in un'interfaccia non ha senso: il tipo concreto - che sarebbe necessario per costruire un'istanza di un tipo - non è noto agli utenti di un'interfaccia. Tutto ciò che un consumatore sa è che un determinato oggetto implementa quell'interfaccia e può essere inviato a vari messaggi.

Tuttavia, non tutta la programmazione è orientata agli oggetti. Quando si usano tecniche come generici o modelli, stiamo usando interfacce / tipi / tratti / concetti per non vincolare oggetti , ma per vincolare tipi . Richiedere che un tipo offra un particolare costruttore ha perfettamente senso. In effetti, alcuni linguaggi (come Rust o Haskell) non hanno un concetto simile di "costruttore", ma solo funzioni ordinarie che capita di restituire un'istanza di quel tipo - e consentono a tali funzioni non di istanza di far parte di un interfaccia.

Di solito non è possibile scrivere un'interfaccia che richiede che un oggetto sia immutabile. Mentre un'interfaccia potrebbe non offrire alcun mutatore, potrebbe fornire metodi aggiuntivi che cambiano il suo stato. Pertanto non sono sicuro che il tuo esempio di IOC possa essere realizzato in un linguaggio tipico.

Riguardo l'esempio di iniezione di dipendenza nella domanda, una soluzione tipica è non iniettare una classe con il suo costruttore, ma iniettare una funzione di fabbrica arbitraria che sia in grado di costruire un oggetto adatto. Questa funzione di fabbrica può avere molte dipendenze possibili ma non deve usarle, permettendoci così di astrarre la firma specifica del vero costruttore. Ad esempio:

function make_A($dep_a, $dep_b) {
  return new ImplementationA($dep_a);
}
function make_B($dep_a, $dep_b) {
  return new ImplementationB($dep_a, $dep_b);
}

// in some configuration:
$DI_CONFIG['SomeInterface'] = make_A;  // or make_B

// in the DI container:
$dep_a = ...;  // resolve dependency
$dep_b = ...;
$some_instance = $DI_CONFIG['SomeInterface']($dep_a, $dep_b)
    
risposta data 29.11.2018 - 22:33
fonte
1

L'interfaccia potrebbe non conoscere il costruttore, ma la classe di implementazione concreta fa e può creare nuovi oggetti immutabili, se necessario. Considera un'interfaccia come (in Scala):

trait Immutable {
    def increment: Immutable
}

Qui, increment restituisce un altro oggetto Immutable . Puoi implementarlo in questo modo:

class Count(count: Int) extends Immutable {
    def increment: Immutable = new Count(count + 1)
}

Count conosce il proprio costruttore, quindi anche se il costruttore non fa parte dell'interfaccia, può ancora essere utilizzato per implementare parti dell'interfaccia. Allo stesso modo, una classe factory potrebbe conoscere internamente su tutti i costruttori per le classi concrete che può costruire.

    
risposta data 29.11.2018 - 23:48
fonte