In questa serie, stiamo studiando come un principiante i linguaggi digitati in modo dinamico (o debolmente tipizzati) e il modo in cui la mancanza di una digitazione forte può influire positivamente e negativamente sulla nostra programmazione.
Come menzionato nel primo post, questa serie è specificatamente orientata ai principianti o verso coloro che non hanno molta esperienza con le lingue poco tipizzate. Vale a dire che se hai programmato in entrambe le lingue fortemente tipizzate e / o debolmente tipizzate e hai familiarità con la coercizione di tipo e le insidie che possono verificarsi quando esegui determinate operazioni, allora questa serie potrebbe non interessarti molto.
D'altra parte, se sei qualcuno che sta appena iniziando a scrivere codice o sei qualcuno che sta entrando in una lingua digitata in modo dinamico da un'altra lingua, allora questa serie è rivolta specificamente a te. In definitiva, l'obiettivo è definire la coercizione di tipo, mostrare come funziona e quindi esaminare le insidie di esso.
Secondo Wikipedia, la coercizione è definita come segue:
In informatica, digitare conversione, typecasting e coercizione sono modi diversi di, implicitamente o esplicitamente, modificare un'entità di un tipo di dati in un altro.
Oppure, forse in un modo più semplice, puoi definire questo come prendere un tipo di dati e convertirlo in un altro. Il fatto è che c'è una linea sottile tra conversione e coercizione.
Come regola generale, tendo a pensare a coercizione come funziona un interprete o un compilatore per determinare che tipo di confronto viene fatto, mentre conversione è un cambio di tipo esplicito che noi, come programmatori, scriviamo nel nostro codice.
Diamo un'occhiata a questo in modo più dettagliato.
Supponiamo, ad esempio, di avere una stringa denominata esempio
e il suo valore è '5'
. Nei linguaggi tipizzati staticamente, puoi digitare cast questo grab il valore della stringa e convertirlo in un int
attraverso un numero di metodi diversi.
Supponiamo di avere un Numero intero
oggetto con a parseInt
metodo. Il metodo accetta una stringa e restituisce il valore della stringa nel tipo di dati intero. Il codice per farlo potrebbe sembrare qualcosa del genere:
string example = '5'; Integer myInt = new Integer (); int intExample = myInt.parseInt (esempio); / * intExample ora ha il valore di 5 (non '5') * e l'esempio si riferisce ancora alla stringa '5' * /
Ovviamente, la sintassi varierà da una lingua all'altra e lì siamo altri modi per lanciare un valore, ma questo ti dà un'idea su come convertire esplicitamente un tipo in un altro.
Un altro modo per farlo è utilizzare un operatore di tipo casting. Sebbene l'implementazione dell'operazione vari da lingua a lingua, la maggior parte dei programmatori che hanno lavorato con linguaggi in stile C probabilmente lo riconosceranno come qualcosa di simile a questo:
int myInt = (int) esempio;
In generale, il casting di tipo viene in genere eseguito posizionando il tipo a cui si desidera convertire la variabile tra parentesi prima della variabile stessa. Nell'esempio sopra, myInt
ora conterrà 5
, piuttosto che '5'
e esempio
rimarrà ancora '5'
.
Come affermato, questo è qualcosa che viene normalmente fatto nel contesto dei linguaggi compilati
Ciò lascia ancora la domanda su come la coercizione di tipo differisca dalla conversione di tipo. Sebbene la coercizione può accade all'interno di linguaggi compilati, è più probabile che lo vedrete accadere all'interno di lingue interpretate o in lingue digitate dinamicamente.
Inoltre, è più che probabile che si verifichi la coercizione di tipo ogni volta che viene effettuato un confronto tra oggetti di tipi diversi o quando viene eseguita un'operazione o una valutazione con variabili che hanno tipi diversi.
Come un semplice esempio, diciamo che in JavaScript abbiamo due variabili - sName
, iage
- dove sName
si riferisce al nome di una persona e iage
si riferisce all'età di una persona. Le variabili, ad esempio, utilizzano la notazione ungherese semplicemente per indicare che uno sta memorizzando una stringa e uno sta memorizzando un numero intero.
Si noti che questo è non un argomento a favore o contro la notazione ungherese - questo è un argomento per un altro post. Viene utilizzato qui per chiarire quale tipo di valore viene memorizzato ogni variabile in modo che sia più semplice seguire il codice.
Quindi andremo avanti e definiremo le nostre variabili e i loro valori:
var sName = 'John Doe'; var iAge = 32;
Ora possiamo esaminare alcuni esempi di come la coercizione di tipo funziona nel contesto di un linguaggio interpretato. Due esempi di come funziona la coercizione di tipo è il seguente:
Diamo un'occhiata a un esempio di ciascuno:
/ ** * Il confronto di un numero con un valore booleano * comporterà il valore booleano * di "falso". * / var result = iAge == true; / ** * Le stringhe e i numeri di concatenazione * costringono il numero a una stringa. * * "John Doe ha 32 anni." * / var bio = sName + 'is' + iAge + 'anni.';
Questi esempi sono relativamente semplici. Il primo ha senso in quanto non è possibile confrontare un numero con un valore booleano.
Nel secondo esempio, notiamo che stiamo prendendo una stringa, concatenandola con un'altra serie di stringhe e utilizzando anche il numero nell'operazione di concatenazione. In questo caso, il numero viene convertito in una stringa e quindi viene concatenato insieme al resto delle parole.
Questa è la coercizione di tipo: quando si prende una variabile di un tipo e si converte il valore in un altro tipo quando si esegue un'operazione o una valutazione.
Il fatto è che entrambi questi esempi sono molto semplicistici. Diamo un'occhiata ad alcuni altri per dimostrare come funziona la coercizione, almeno in JavaScript, quando si eseguono operazioni di concatenazione:
var uno, due, risultato; // uno e due si riferiscono ai valori stringa di '1' e '2' uno = '1'; due = '2'; // result conterrà la stringa '12'; risultato = uno + due; // ridefinire due per uguagliare il numero '2' due = 2; // concatenando una stringa e un numero risulta in una stringa // result conterrà '12'; risultato = uno + due; // ridefinisce uno come numero uno = 1; // quindi concatena (o somma) i due valori // risultato sarà 3 risultato = uno + due;
Ci sono due cose importanti da notare:
+
l'operatore è sovraccarico. Ciò significa che quando lavora con le stringhe, le concatena insieme, ma quando funziona con i numeri li aggiunge insieme.Per fare un esempio, aggiungiamo un'altra variabile, una serie di operazioni prioritarie, quindi esaminiamo il risultato:
var uno, due, albero, risultato; uno = '1'; due = 2; tre = 3; // risultato è risultato '123' = uno + due + tre; // risultato è risultato '15' = uno + (due + tre);
Notare nel secondo esempio, Due
e tre
siamo aggiunto insieme perché sono entrambi numeri e quindi il risultato è concatenati con uno
perché è una stringa.
In precedenza, abbiamo detto che esiste un caso speciale per numeri e valori booleani, almeno in JavaScript. E poiché questo è il linguaggio che abbiamo usato per esaminare la coercizione di tipo e dal momento che si tratta di un linguaggio che viene frequentemente utilizzato nel moderno sviluppo web, diamo un'occhiata.
Nel caso di JavaScript, tieni presente che 1
è considerato un valore "vero" e 0
è preoccupato di essere un valore "falso". Queste parole sono scelte come tali perché i valori possono servire come numeri, ma saranno anche valutati vero
o falso
quando si esegue un confronto.
Diamo un'occhiata ad alcuni esempi di base:
var bTrue, bFalse, iZero, iOne, result; bTrue = true; bFalse = false; iZero = 0; iOne = 1; // result contiene il valore booleano di false result = bTrue == iZero; // result contiene il valore booleano di true result = bTrue == iOne; // result contiene il valore booleano di false result = bFalse == iOne; // result contiene il valore booleano di true result = bFalse == iZero;
Si noti che negli esempi sopra, i valori numerici sono costretto in valori interi per natura del confronto che viene effettuato.
Ma cosa succede se vogliamo confrontare un valore booleano di vero
o falso
a un valore stringa di uno
o zero
?
var bTrue, bFalse, sTrue, sFalse, result; bTrue = true; bFalse = false; sTrue = '1'; sFalse = '0'; // result contiene true result = bTrue == sTrue; // result contiene false result = bTrue == sFalse; // risultato contiene false; risultato = bFalse == sTrue; // result contiene true result = bFalse == sFalse;
A questo punto, le cose possono iniziare a diventare veramente confuse perché stiamo confrontando un valore stringa di un numero che è 1
a un valore booleano di vero
e stiamo ottenendo un risultato booleano, e il booleano è vero
.
Ha senso? Daremo un'occhiata a questo in modo più dettagliato nel prossimo articolo, ma volevo andare avanti e introdurre le basi di esso prima.
Questo è quando le lingue digitate dinamicamente possono iniziare a causare mal di testa per gli sviluppatori. Fortunatamente, ci sono modi in cui possiamo scrivere codice più severo di quello che abbiamo sopra e che produce risultati accurati.
Inoltre, alcune lingue digitate dinamicamente contengono anche valori per non definito
e per nullo
. Questi mantengono anche valori "veri" e "falsi" che, a loro volta, influenzano il modo in cui affrontiamo i confronti.
Nell'articolo finale della serie, daremo un'occhiata a valori come non definito
e nullo
confrontarsi con altri valori e con gli altri e dare un'occhiata ad alcune strategie che possiamo implementare che renderanno il nostro codice più resistente contro la coercizione di tipo errata, e che lo rende più leggibile.
Se questa è la tua prima incursione in lingue digitate dinamicamente o tipo coercizione e hai domande, commenti o feedback, allora non esitare a lasciare un commento nel feed qui sotto!