Una classe standard o molte classi simili?

3

Diciamo che sto provando a modellare una varietà di oggetti che sono praticamente identici, con l'unica differenza che sono le loro variabili di classe. Sto meglio creando una classe boilerplate e chiamando semplicemente il costruttore con le variabili specifiche, o creando un sacco (in questo caso 100+) di classi essenzialmente identiche e codificando con hard disk le loro variabili di classe (che non cambieranno mai)?

Per essere chiari:

  • Metodi identici
  • Nomi di variabili di classe identiche ma valori diversi
  • Funzionalità prevista identica

Per essere chiari, il mio linguaggio (Python) non supporta le interfacce di cui sono a conoscenza - alcune delle altre domande simili sembravano avere risposte che lo consigliavano. L'altra opzione che sembra avere senso per me sarebbe quella di creare una classe base con ogni campo e metodo e quindi creare un gruppo di classi child univoche che contengono i loro valori univoci.

La quantità di lavoro per creare tutte le classi figlie non è significativa per me - Ho scritto un programma che analizza rapidamente un file di testo (che ha tutti i valori univoci) e può scrivere tutte le classi in una .py file rapidamente e facilmente. Fare le modifiche lungo la strada è piuttosto facile per lo stesso motivo.

(un po ') Domande correlate

posta Dannnno 17.08.2014 - 23:52
fonte

2 risposte

4

Oltre 100 classi quasi identiche sono pazze. Le classi sono strutture organizzative. Avere dozzine di loro con quasi nessuna variazione non sembra utile. È un'eccessiva specializzazione.

Sembra molto che tu abbia bisogno di una singola classe con una tabella di ricerca condivisa che definisce le informazioni condivise. Qualcosa come:

from collections import namedtuple

Lang = namedtuple('Lang', 'style points creator')

LANG_FORM = {
    'Python': Lang('dynamic', 84, 'Guido van Rossum'),
    'Java':   Lang('static', 65, 'James Gosling'),
    # ...
    'Pascal': Lang('static', 33, 'Niklaus Wirth')
}

class Protean(object):

    def __init__(self, name, form):
        self.name = name
        self.form = form
        self.lang = LANG_FORM[form] # optional

    # methods here

Qui LANG_FORM può essere una variabile globale (quasi costante), o potrebbe essere una variabile di classe. Ad ogni modo, ogni istanza diventa fondamentalmente solo un puntatore indietro alle sue informazioni condivise (ciò che si fa riferimento come variabili di classe). Non è nemmeno strettamente necessario, se sei disposto a indicizzare LANG_FORM ogni volta che ne hai bisogno, piuttosto che memorizzarlo in ogni istanza.

Se vuoi che ognuna delle istanze si dipinga in base alla sua forma / tipo / quasi-classe, aggiungi un metodo __repr__ :

def __repr__(self):
    classname = self.__class__.__name__
    return "{0}-{1}({2!r}, {3})".format(classname, self.form, self.name, self.lang.points)

Quindi:

p = Protean('CPython', 'Python')

print p

I rendimenti:

Protean-Python('CPython', 84)
    
risposta data 10.09.2014 - 05:03
fonte
2

Se il comportamento è lo stesso per tutte le classi e hanno tutte lo stesso motivo per cambiare, allora probabilmente non avrei sottoclasse affatto.

È una questione di istanziazione e configurazione - influenza solo l'uso della classe ma non la struttura. Quindi fondamentalmente stiamo parlando di trade off nell'uso della classe e della sua manutenzione.

Se hai un istante facile istanatiando i tuoi oggetti da un'origine dati che usi per generare le classi, allora perché non farlo? Se il costruttore richiede solo tre facili da ricordare o facili da consultare, perché la sottoclasse? Non c'è motivo di creare così tante classi.

Generare le classi d'altra parte può rivelarsi una manutenzione più difficile, poiché è necessario mantenere la classe base e anche i generatori se per qualche motivo - e contrariamente alle tue aspettative - le cose cambiano.

Posso solo pensare ad un motivo per optare per le sottoclassi: quando rende la tua API notevolmente più semplice e il tuo codice più facile da capire. Ad esempio, quando la tua classe viene istanziata molto spesso dal programmatore ed è più facile per lei / lui ricordare il nome della classe invece di un qualificatore difficile da ricordare per i dati che devono essere recuperati dall'origine dati. O se non è assolutamente possibile recuperare i dati con un qualificatore e il programmatore deve cercare o calcolare molti valori per istanziare la classe. IMHO è una sorta di convenzione sulla configurazione e può davvero rivelarsi un miglioramento dell'API, specialmente se la sottoclasse è il luogo naturale in cui cercare i valori se un programmatore deve cercarli. Ma in molti casi dovresti anche essere in grado di adattare il formato della tua fonte di dati in modo che gli umani possano interagire facilmente con esso.

Un altro motivo per generare i sublassaggi è quando - anche in contrasto con le tue aspettative - ti rendi conto che avrai bisogno di un comportamento migliorato almeno in alcuni di essi.

To be clear, my language (Python) doesn't support interfaces that I'm aware of - some of the other similar questions seemed to get answers recommending that.

Questo perché il linguaggio digitato dinamicamente non ha bisogno di interfacce. Mose usa digitazione anatra .

    
risposta data 18.08.2014 - 00:46
fonte