L'interfaccia che contiene ogni metodo della classe data è una buona cosa?

1

Sto cercando di scrivere un gioco semplice e voglio davvero creare qualcosa che sia "programmaticamente corretto". Mi sono bloccato con un problema del genere: ho classe

public abstract class ProjectileLogic<T> where T : ProjectileInfo{
    protected T _projectileInfo;
    public abstract void OnInitialize();
    public abstract void OnHitTerrain(Vector2 hitDirection);  //hitting the floor should give Vector2.down, etc.
    public abstract void OnHitEnemy();
    public abstract void Destroy();
}

Sto usando i generici, perché l'ereditare le classi ha bisogno di oggetti diversi che ereditano dalla classe ProjectileInfo. ProjectileInfo contiene dati come danni, velocità iniziale ecc.

Il problema appare, quando spawner crea il proiettile e chiama "OnInitialize".

var projectile = spawner.CreateProjectile(ProjectileType.Pellet);
projectile.GetComponent<ProjectileLogic<...what exactly?...>>().OnInitialize();

GetComponent restituisce il componente associato all'oggetto di gioco "proiettile" di un determinato tipo.

Ho pensato, potrei creare un'interfaccia IProjectileLogic contenente tutti i metodi di ProjectileLogic e quindi:

public class ProjectileLogic<T> : IProjectileLogic where T : ProjectileInfo{
    protected T _projectileInfo;
}

e quindi spawner:

var projectile = spawner.CreateProjectile(ProjectileType.Pellet);
projectile.GetComponentByInterface<IProjectileLogic>().OnInitialize();

Ma davvero non so se non sarebbe un uso improprio delle interfacce e delle cattive pratiche usate solo perché "aiuta in questo singolo caso".

    
posta user3387666 14.07.2016 - 13:32
fonte

3 risposte

1

Lo scopo di avere un'interfaccia è che tu possa dichiarare una variabile di tipo di quell'interfaccia, e quindi effettivamente popolare quella variabile con qualsiasi classe che implementa l'interfaccia, e tutte le funzioni dichiarate nell'interfaccia saranno essere disponibile. Cioè, l'interfaccia dovrebbe dichiarare tutte le funzioni che si desidera utilizzare nei casi in cui potrebbe essere popolata con diverse classi diverse.

Non so esattamente cosa stai facendo con la tua classe "proiettile", ma per inventare un semplice esempio, supponiamo di avere un sistema con oggetti per diversi tipi di persone: clienti, dipendenti e azionisti. Tutti questi tipi di persone hanno nomi e indirizzi. Ho una funzione che formatta gli indirizzi e li stampa su buste. Ha senso scrivere questa funzione una sola volta e usarla per tutti e tre i tipi di persone piuttosto che scriverla tre volte. Quindi creo un'interfaccia, Person. Quindi realizzo oggetti Cliente, Dipendente e Stockholder implementano Persona.

A questo punto, Person richiede solo due funzioni: GetName e GetAddress. Quasi certamente non includerebbe tutte le funzioni in tutte e tre le classi di implementazione. Ci sono probabilmente cose che faccio con dipendenti che non faccio con i clienti, come calcolare l'ammontare della loro busta paga e iscriverli al piano assicurativo aziendale. Ci sono cose che faccio per gli azionisti che non faccio per i dipendenti, come invitare loro gli inviti all'assemblea annuale degli azionisti. Ecc.

Ci sono casi in cui un'interfaccia avrebbe tutte le funzioni presenti nelle classi di implementazione. Forse l'unica differenza tra le implementazioni è come facciamo qualcosa, e cosa deve essere fatto.

Ma non penso che rendere l'interfaccia abbia ogni funzione che è nelle classi di implementazione dovrebbe essere una sorta di obiettivo. Se succede in questo modo, bene. Se no, allora?

    
risposta data 14.07.2016 - 15:23
fonte
0

In termini di principio SOLID, non forzare l'implementazione su classi che non ne hanno bisogno. I generici sono carini, ma tendono a portare a un prematuro refactoring e piccionaia nell'usare il tipo atteso. Se desideri rifattorizzare le tue interfacce, i tuoi generici ti daranno un sacco di mal di testa.

Suggerirei di separare le tue interfacce. Ecco un grande esempio, mi ritrovo a riferirmi all'infinito nel corso degli anni.

link

    
risposta data 14.07.2016 - 16:12
fonte
0

Risposta breve: no. Farlo "giusto" può metterti nei guai se non sai perché la regola che stai seguendo è lì, e quindi se si applica nel tuo caso. Stai lavorando sui principi SOLID , dei quali stai cercando di seguire D: Principio di inversione delle dipendenze .

In questo caso, hai una classe e un'interfaccia, ma non sai perché li stai separando, quindi non sai cosa ti appartiene. Cioè, hai codice di interfaccia ma nessuna interfaccia concettuale: nessun contratto che l'interfaccia implichi. Così finisci per scrivere due volte tutte le firme dei tuoi metodi, il che rende il codice più difficile da leggere e modificare, tutto inutilmente.

Non so nulla di Unity 3D, ma sembra che utilizzi Dependency Injection e potrebbe richiedere un'interfaccia. Se è così, stai facendo quello che ti serve. Altrimenti disinserisci l'interfaccia e usa solo una classe.

L'obiettivo non è quello di ottenere un codice perfetto, ma di essere in grado di spostarsi verso un codice migliore. La tua classe è il prototipo che ti aiuta a progettare l'interfaccia che ti serve, e potrebbe essere tutto ciò di cui hai bisogno.

Ciò significa che dovresti preoccuparti meno della scrittura di un'interfaccia e di più sulla possibilità di convertire un'interfaccia in futuro.

    
risposta data 11.11.2016 - 20:45
fonte

Leggi altre domande sui tag