Falcon - il linguaggio



Gli oggetti              
 
Falcon dispone di un potente sistema a oggetti che include tra le altre cose anche l'ereditarietà multipla, in certe condizioni e mi sento di sottlinearlo in quanto sembra diventata un rarità, tra i moderni linguaggi. Tra i linguaggi ad alta diffusione direi che solo C++ e Python permettono questo approccio. Tutti gli altri hanno escamotage di vario tipo per permettere le stesse funzionalità evitando le problematiche connesse all'ereditarietà multipla. Io sono comunque favorevole ad essa, insomma, a me piace anche se riconosco che non sia assolutamente necessaria. Detto questo passiamo a Falcon.

Cominciamo a parlare di oggetti stand alone. In questo senso un oggetto nel nostro linguaggio, come in altri, è una entità dotata di certe proprietà. Le proprietà possono essere variabili oppure funzioni (che possiamo chiamare più comunemente metodi). Un piccolo esempio tanto per chiarire:

  Esempio 10.1
1
2
3
4
5
6
7
8
9
10
11
12
object sommatore
  valore = 0
  function aumenta (dato)
    self.valore += dato
  end
  function mostra()
    > self.valore
  end
end

sommatore.aumenta(5)
sommatore.mostra()

alla riga 1 viene presentato il nostro oggetto, la riga 2 espone la proprietà "variabile" valore mentre alla 3 e alla 6 vengono definiti due metodi. Da notare che se il nome di una proprietà inizia col carattere _ (underscore) questo equivale a fornire una sorta di "protezione" alla variabile stessa. Come in altri linguaggi alla moda l'operatore . (punto) serve per arrivare alle proprietà della classe. Da notare la parola self che serve per lavorare su oggetto dall'interno dello stesso (un po' this in C#, per intenderci). Self è anche utile per identificare una variabile esterna ad un metodo di oggetto che contenga una variabile con lo stesso nome. Ovvero:

object a
val =5
function b()
  val = 1
  x = val + self.val // x vale 6 = 1 + 5
end


Una interessante caratteristica è che se pure non è possibile definire nuove proprietà e metodi in un oggetto già definito (un linguaggio che permette questo mi pare sia Ruby) è tuttavia permesso modificarle e in qualche modo aggirare questa limitazione. Vediamo ampliando l'esempio 10.1

  Esempio 10.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
object sommatore
  valore = 0
  function aumenta (dato)
    self.valore += dato
  end
  function mostra()
    > self.valore
  end
end

function nuovo_aumenta(nuovo_dato)
self.valore *= nuovo_dato
end

sommatore.aumenta(5)
sommatore.mostra()

vecchio_aumenta = sommatore.aumenta
sommatore.aumenta = nuovo_aumenta

sommatore.aumenta(5)
sommatore.mostra()
vecchio_aumenta(3) //funziona ancora!
sommatore.mostra()

Se eseguite il programma noterete come il nuovo metodo "aumenta" si comporti come la funnzione "nuovo_aumenta", moltiplicando invece di sommare (infatti l'output chiamata alla riga 22 è 25 invece di 10. Tuttavia l'output esposto in forza della riga 24 dimostra che il vecchio metodo è ancora lì, vivo e vegeto.
L'introduzione degli oggetti ci permette anche di annotare un interessante comportamento delle funzioni che sono in grado di riconoscere se sono chiamate di per se stesse o come metodi di un oggetto. Nell'esempio che segue, ispirato come sempre alla guida on line di Falcon, vediamo anche l'assegnazione di una funzione ad una variabile. L'elasticità di Falcon è impareggiabile.

  Esempio 10.3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function maybe_method()
  if self == nil
    printl( "Sono una funzione" )
  else
    printl( "Sono un metodo" )
  end
end

object test
property = 0
end

maybe_method()
test.property = maybe_method
test.property()
maybe_method()

Gli strumenti per la gestione degli oggetti non finiscono qui. Prima di proseguire dobbiamo presentare altri due strumenti di analisi.
provides(oggetto, operando) - permette di verificare se un certo oggetto contiene una certa proprietà.

  Esempio 10.4
1
2
3
4
5
6
7
object test
x = 0
end

if test provides x
> "est!"
end

Il secondo strumento è l'eclettico in che permette invece di verificare se una certa stringa corrisponde al nome di una proprietà all'interno di un oggetto.

  Esempio 10.5
1
2
3
4
5
6
7
object test
xx = 0
end

if "xx" in test
> "est!"
end

Questo è tutto (per ora ;-)) relativamente agli oggetti stand alone. Dopo la spiegazione delle classi arriverà altro materiale anche per gli oggetti stessi.