Perché Java non utilizza l'incapsulamento con alcune classi?

24

La mia domanda è correlata alle classi System.in e System.out (potrebbero essercene altri come quelli nella libreria Standard). Perché? Non è una cattiva pratica in OOP? Non dovrebbe essere usato come: System.getIn() e System.getOut() ? Ho sempre avuto questa domanda e spero di trovare una buona risposta qui.

    
posta Clawdidr 12.08.2013 - 16:40
fonte

4 risposte

35

La definizione dei campi in e out nella classe System sono:

public final static PrintStream out;
public final static InputStream in;

Queste sono costanti. Anche loro sono oggetti, ma sono costanti. È molto simile alla classe Math:

public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;

O nella classe booleana:

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);

O nella classe Color:

public final static Color white     = new Color(255, 255, 255);
public final static Color black     = new Color(0, 0, 0);
public final static Color red       = new Color(255, 0, 0);

Quando si accede a una costante pubblica che non cambia, non c'è un vantaggio significativo per incapsularlo - concettualmente o basato sulle prestazioni. È lì. Non cambierà.

Non c'è una vera differenza tra Color.white e System.out .

    
risposta data 12.08.2013 - 17:22
fonte
5

La vera ragione è che si tratta di un problema precedente. Le costanti System.in,out,err facevano parte di Java 1.0 ... e probabilmente molto più indietro. Quando fu chiaro che il design aveva problemi, era troppo tardi per sistemarlo. Il meglio che potevano fare era aggiungere i metodi System.setIn,setOut,setErr in Java 1.1 e poi affrontare i problemi con le specifiche del linguaggio 1 .

Questo è simile al motivo per cui esiste un metodo System.arraycopy statico il cui nome viola le convenzioni di denominazione Java.

Per quanto riguarda se questo è "cattivo design" o no, penso che lo sia. Ci sono situazioni in cui l'attuale gestione non OO è un problema serio. (Pensa ... come puoi eseguire un programma Java dentro un altro quando i loro requisiti di flusso "IO standard" sono in conflitto, pensa ... codice di test dell'unità che comporta la modifica dei flussi.)

Tuttavia, posso anche riferire all'argomento che il modo attuale di fare le cose è più conveniente in molti casi.

1 - È interessante notare che le variabili System.in,out,err ricevono una menzione speciale nel JLS come "semantica speciale". Il JLS dice che se si modifica il valore di un campo final , il comportamento non è definito ... tranne nel caso di questi campi

    
risposta data 13.08.2013 - 04:08
fonte
2

Credo che l'oggetto out sia immutabile, il che lo rende in qualche modo sicuro (è discutibile) per essere tenuto in un campo statico finale pubblico.

Molte delle classi nel JDK non rispettano i migliori principi di progettazione orientati agli oggetti. Una ragione di ciò è il fatto che sono stati scritti quasi 20 anni fa, quando Object-Orientation stava emergendo solo come un paradigma mainstream e molti programmatori semplicemente non avevano familiarità con loro come lo sono ora. Un ottimo esempio di design API scadente è il Date & Time API, che impiegò 19 anni per cambiare ...

    
risposta data 12.08.2013 - 16:59
fonte
2

Questa risposta è eccezionale e vera.

Volevo aggiungere che in alcuni casi i compromessi sono stati creati per l'usabilità.

Gli oggetti di tipo String possono essere istanziati senza nuovo, evento quando String non è una primitiva:

String s = "Hello";

String essendo un non-primitivo, dovrebbe essere istanziato in questo modo:

String s = new String("Hello");          // this also works 

Ma il compilatore consente l'opzione OO più breve, meno, perché la stringa è di gran lunga la classe più utilizzata nell'API.

Anche gli array possono essere inizializzati in modo non OO:

int i[] = {1,2,3};

Stranamente, un oggetto è un'istanza di una classe o di un array . Gli array di significato sono un tipo di classe completamente separato.

Le matrici hanno un campo pubblico length che non è una costante. Inoltre non c'è documentazione sugli array di classe sono un'istanza di. (non confondere con la classe Arrays o java.reflect.Array).

int a = myArray.length;    // not length()
    
risposta data 12.08.2013 - 17:32
fonte

Leggi altre domande sui tag