Oggetto passato a super () a cui fa riferimento la sottoclasse - Qualsiasi violazione?

1

Questo è il codice in questione, i commenti lo indicano:

class Actor extends Entity {
    private MutableVector2f position;
    private MutableIdentity identity;

    public Actor(MutableVector2f initialPosition, MutableIdentity initialIdentity) {
        super(initialPosition, initialIdentity); // !! pass to supertype !!

        this.position = initialPosition; // !! reference in subtype !!
        this.identity = initialIdentity; // !! "" "" !!
    }

    public void moveTowards(Vector2f targetPosition) {
        // !! change position member, purpose of keeping reference !!
    }

    public void changeNameTo(String name) {
        identity.changeNameTo(name);
    }
}

Sembra un odore di codice. È? Forse c'è un problema con la struttura dei tipi?

Ci sono delle cadute verso questo tipo di design?

La classe base Entity viene utilizzata per qualsiasi oggetto con una posizione:

abstract class Entity {
    private Vector2f position;
    private Identity identity;

    public Entity(Vector2f position, Identity identity) {
        this.position = position;
        this.identity = identity;
    }

   public Vector2f getPosition() {
       return position;
   }

   public Identity getIdentity() {
       return identity;
   }
}

Il sottotipo Actor ha una posizione mutabile per ridurre la quantità di oggetti creati (potrebbe avere centinaia di migliaia di attori che si muovono e cambiano identità)

Il sottotipo WorldObject ha una posizione e un'identità immutabili:

class WorldObject extends Entity {
    public WorldObject(ImmutableVector2f position, ImmutableIdentity identity) {
        super(position, identity);
    }
}

Vector2f è un'interfaccia che implementa "ImmutableVector2f and MutableVector2f":

interface Vector2f {
    float getX();
    float getY();
}

MutableVector2f espone metodi come add , multiply e normalize .

Identity segue la stessa struttura (è un'interfaccia, ha sottotipi immutabili e mutabili)

Ritengo che ciò possa violare LSP. Lo scopo delle interfacce è impedire la modifica da una prospettiva Entity .

Non vuol dire che Entity è immutabile, ma per scoraggiare la mutazione a quel livello di astrazione, poiché i sistemi che usano Entity dovrebbero solo leggere valori.

Mantenere un riferimento nella sottoclasse impedirà la necessità di lanciare Entity#getPosition() , ma sembra sbagliato. Rendere le proprietà generiche potrebbe portare a una lunga lista di parametri di tipo se dovessi continuare a scalare Entity in questo modo.

È possibile che Entity#getPosition() debba essere astratto e i sottotipi dovrebbero mantenere le proprie variabili di posizione? Mi richiederebbe di dichiarare i getter nei sottotipi (codice duplicato), quindi non sono un grande fan dell'idea.

    
posta Vince Emigh 25.03.2017 - 05:47
fonte

1 risposta

1

Se Entity specifica in qualche contratto (documentazione, commenti?) che la sua posizione non deve cambiare dopo la sua costruzione iniziale, questo viola l'LSP (e gli invarianti della classe base).

Se non specifica esplicitamente una cosa del genere, potrebbe comunque essere un'ipotesi implicita. Ma dato il modo in cui Java funziona, non mi aspetterei una cosa del genere. Tuttavia, cambiare getPosition per essere astratto renderebbe più esplicito il fatto che le sottoclassi abbiano il controllo sulla posizione.

Se non esiste alcuna ipotesi, l'LSP non viene violato.

    
risposta data 25.03.2017 - 18:21
fonte