JavascriptProva

sabato 11 febbraio 2012

Classe in Java e C++

Continuiamo a rivangare un po' di Java...

Ecco:
class Persona{
    String nome;
    String cognome;
    int altezza;     
}

public class Main {
    
    public Main() {
    }
    
    public static void main(String[] args) {
        Persona Mario=new Persona();
        Mario.nome="Mario";
        Mario.cognome="Rossi";
        Mario.altezza=177;       
    }  
}
Ho creato un'istanza della classe Persona, chiamata Mario.
Una volta creata l'istanza, manipolo le sue proprietà.

Adesso ripassiamo la sintassi C++...
Vediamo piano piano come si dichiarano le classi...
class Persona{
public:
 char* nome;
 char* cognome;
 int altezza;
};
void main(){
 Persona Mario;
 Mario.nome="Mario";
 Mario.cognome="Rossi";
 Mario.altezza=176;
 printf(Mario.nome);
 printf(Mario.cognome);
 getchar();
}
Bene.
Confronto:

In Java sembrerebbe che i membri della classe vengano ritenuti di base pubblici, mentre in Cpp verrebbero ritenuti di base privati. Infatti se io faccio questo in Java:
class Persona{
    private String nome;
    String cognome;
    int altezza;    
}

public class Main {
    
   
    public Main() {
    }
    
   
    public static void main(String[] args) {
        Persona Mario=new Persona();
        Mario.nome="Mario";
        Mario.cognome="Rossi";
        Mario.altezza=177;
        
    } 
}
ottengo questo messaggio di errore:
C:\Users\Io\JavaApplication1\src\javaapplication1\Main.java:34: nome has private access in javaapplication1.Persona


In Cpp, invece, se faccio questo:
class Persona{

 char* nome;
public:
 char* cognome;
 int altezza;
};
void main(){
 Persona Mario;
 Mario.nome="Mario";
 Mario.cognome="Rossi";
 Mario.altezza=176;
 printf(Mario.nome);
 printf(Mario.cognome);
 getchar();
}
ottengo questo:
1>c:\users\io\documents\visual studio 2010\projects\progetto\progetto\uno.cpp(12): error C2248: 'Persona::nome': impossibile accedere a private membro dichiarato nella classe 'Persona'
E questa è una delle differenze...
private, in ambedue i linguaggi, significa che il membro può essere visto solo all'interno della classe stessa.
Almeno credo...

Mi esercito a richiamare dalla memoria come si compongono le classi in Java.

Ora, come si aggiungono proprietà e metodi a una classe in Java?

Cerco di tenere sempre un occhio comparativo al Javascript, e magari anche al C++.

Alla classe Java si deve aggiungere un costruttore.
Se ricordo bene, il costruttore senza parametri è di default, e se ci sono costruttori con parametri deve essere dichiarato obbligatoriamente, se lo si vuole, il costruttore senza parametri... Queste sono regole valide con il C++, ma dovrebbero essere valide anche per il Java.

Adesso creo una classe Persona, e ne creo un'istanza con la sintassi adeguata per il Java:
class Persona{
    int nome;
    int cognome;
    int altezza;
    
     
}

public class Main {
    
    /** Creates a new instance of Main */
    public Main() {
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Persona Mario=new Persona();
    }
    
}
Ecco, con questo NetBeans non mi dà alcun messaggio di errore.
Solo che ho avuto una svista: nome e cognome non sono numeri, quindi non possono essere di tipo int.
La pratica col Javascript mi ha un po' disabituato ai linguaggi fortemente tipizzati!

Riesumando reminiscenze di Java...

NetBeans.
Non mi ricordo quasi più niente di come si programma a oggetti in Java.

Questo è ciò che appare inizialmente in NetBeans:
package javaapplication1;

/**
 *
 * @author Io
 */

public class Main {
    
    /** Creates a new instance of Main */
    public Main() {
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
    }
    
}


Ora creo un'altra classe nello stesso modulo.
Se ricordo bene, non si possono avere più classi pubbliche nello stesso modulo.
Ecco:
package javaapplication1;

/**
 *
 * @author Io
 */

class Classe{
     
}
public class Main { /** Creates a new instance of Main */ public Main() { } /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here } }
Ecco, NetBeans non mi segnala errore...

Viceversa, mi segnala errore in questo caso:
package javaapplication1;

/**
 *
 * @author Io
 */

public class Classe{
     
}

public class Main {
    
    /** Creates a new instance of Main */
    public Main() {
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
    }
    
}
Un errore di questo tipo:
C:\Users\Io\JavaApplication1\src\javaapplication1\Main.java:17: class Classe is public, should be declared in a file named Classe.java
...confermando il mio ricordo che non si può dichiarare più di una classe public in un solo modulo.

venerdì 10 febbraio 2012

Granelli di Glasgow

Captare singoli gesti può essere molto utile...

Il rianimatore ha detto al paziente in coma: "Mostra la lingua".
Quindi lo ha pizzicato osservando che portava la mano del lato non paretico verso la sede del pizzicamento.

Questi sono elementi che fanno parte della valutazione della risposta motoria del GCS, e precisamente dei punteggi 5 e 6
Il grado 5 di risposta motoria è quello messo in luce dall'applicazione di uno stimolo doloroso.
Il grado 6 è quello che sarebbe stato messo in luce se il paziente avesse mostrato la lingua dietro ordine del rianimatore.

Teniamo in conto queste acquisizioni per costruire un modo di procedere spontaneo e ragionato...

Una proprietà unica della classe genitrice per le classi derivate...

Ho un'altra idea per vedere se con classi derivate si può instaurare quel tipo di confusione di cui parla il sito che sto seguendo...
Ci provo.

Inizio con il creare una classe Madre e una classe Figlia.
function Madre(){
 var nome="";
 this.nomina=function(n){
  nome=n;
 }
 this.presentati=function(){
  alert("Mi chiamo "+nome);
 }
} 

function Figlia(){
 var soprannome="";
}


Figlia.prototype=new Madre();
Ora creo due istanze della classe Madre e le nomino. Si dovrebbero presentare ognuna con il suo nome:
Maria=new Madre();
Maria.nomina("Maria");

Lucia=new Madre();
Lucia.nomina("Lucia");

Maria.presentati();
Lucia.presentati();
...e ottengo "Mi chiamo Maria" e "Mi chiamo Lucia". Come previsto.
Ora creo due istanze della classe Figlia...
Barbara=new Figlia();
Barbara.nomina("Barbara");

Giuliana=new Figlia();
Giuliana.nomina("Giuliana");

Barbara.presentati();
Giuliana.presentati();
E cosa ottengo?
Ottengo per due volte "Mi chiamo Giuliana"!

Se inverto le due:
Giuliana=new Figlia();
Giuliana.nomina("Giuliana");

Barbara=new Figlia();
Barbara.nomina("Barbara");


Giuliana.presentati();
Barbara.presentati();
Ottengo per due volte "Mi chiamo Barbara"!

Evidentemente la funzione Madre viene utilizzata da ambedue, e mentre all'inizio il metodo nomina dell'istanza Barbara modifica la variabile nome in "Barbara", successivamente il metodo nomina dell'istanza Giuliana modifica la stessa variabile nome in "Giuliana".
O viceversa.

La soluzione?

<script>

function Madre(){
 var nome="";
 this.nomina=function(n){
  nome=n;
 }
 this.presentati=function(){
  alert("Mi chiamo "+nome);
 }
} 

function Figlia(){
 Madre.call(this);
 var soprannome="";
}

Figlia.prototype=new Madre();


Giuliana=new Figlia();
Giuliana.nomina("Giuliana");

Barbara=new Figlia();
Barbara.nomina("Barbara");


Giuliana.presentati();
Barbara.presentati();

</script>
Il fatto è che le istanze della classe derivata condividono una sola istanza della classe genitrice. Se una variabile in questa non è dichiarata this, si fa riferimento a una sola variabile, che viene modificata ora da una ora dall'altra istanza. Non è molto facile, ma sembra che ci sto cominciando a capire qualcosa, dato che sono riuscito a personalizzare l'esempio del tutorial creandomi, come sempre un esempio tutto mio.

giovedì 9 febbraio 2012

Una proprietà come array di oggetti, e varie implicazioni...

Ecco, sto cercando di riprodurre il discorso che vuole fare il famoso blog di uno molto più bravo di me, a proposito delle implicazioni dell'ereditarietà in Javascript.

Ho creato una classe Veicolo, che carica oggetti anzichè numeri.
Ossia il suo metodo carica() non ha come parametro un numero di passeggeri ma un oggetto passeggero, istanza della classe Persona.
Questa va posta in un Array che è la proprietà passeggeri della classe Veicolo.

Ecco:
<script>
function Persona(nome){
 this.nome=nome;
}
function Veicolo(passeggero){
 this.passeggeri=[]
 this.carica=function(passeggero){
  this.passeggeri.push(passeggero);
 }
}

Auto=new Veicolo();
Mario=new Persona("Mario");
Giuseppe=new Persona("Giuseppe");
Auto.carica(Mario);
Auto.carica(Giuseppe);
for(n=0;n<Auto.passeggeri.length;n++){alert(Auto.passeggeri[n].nome);}

</script>
Ottengo due caselle di testo con i nomi "Mario" e "Giuseppe".


Ora però riprovo l'esperimento che viene suggerito sul blog... ossia faccio caricare a un veicolo Mario e all'altro Giuseppe.
<script>
function Persona(nome){
 this.nome=nome;
}
function Veicolo(passeggero){
 this.passeggeri=[]
 this.carica=function(passeggero){
  this.passeggeri.push(passeggero);
 }
}

Auto1=new Veicolo();
Auto2=new Veicolo();
Mario=new Persona("Mario");
Giuseppe=new Persona("Giuseppe");

Auto1.carica(Mario);
Auto2.carica(Giuseppe);
for(n=0;n<Auto1.passeggeri.length;n++){alert("Sull'Auto1 ci sono "+Auto1.passeggeri[n].nome);}
for(n=0;n<Auto2.passeggeri.length;n++){alert("Sull'Auto2 ci sono "+Auto2.passeggeri[n].nome);}
</script>
...Embeh?

Paradosso! Il codice funziona egregiamente, e mi dice che sull'Auto1 c'è Mario e sull'Auto2 c'è Giuseppe!
Eppure secondo il "maestro" non dovrebbe funzionare, e dovrebbe specificarmi che invece Mario e Giuseppe si troverebbero paradossalmente su tutte e due le auto!

Perchè?

Forse è perchè nell'esempio del sito la proprietà passeggeri non è dichiarata con il this ma con il var.

Proviamo...

Dato che la variabile dichiarata con il var risulta privata, ossia non visibile all'esterno della funzione, devo crearmi un metodo che mi "metta all'esterno" i valori contenuti in essa.
<script>
function Persona(nome){
 this.nome=nome;
}
function Veicolo(passeggero){
 this.passeggeri=[]
 this.carica=function(passeggero){
  this.passeggeri.push(passeggero);
 }
 this.listaPasseggeri=function(){
  for(n=0;n<this.passeggeri.length;n++){alert(this.passeggeri[n].nome);}
 }
}

Auto1=new Veicolo();
Auto2=new Veicolo();
Mario=new Persona("Mario");
Giuseppe=new Persona("Giuseppe");

Auto1.carica(Mario);
Auto2.carica(Giuseppe);

Auto1.listaPasseggeri();
Auto2.listaPasseggeri();
</script>
Ecco: così ottengo DUE caselle di testo con scritto Mario (il passeggero di Auto1) e Giuseppe (il passeggero di Auto2).
Tutto regolare!

E se rendo privata la proprietà passeggeri? Mi sa che non ho capito molto bene la lezione del "maestro"...

Codice e alcuni metodi per gli Array

Ora il discorso si fa un po' difficile...

Sarebbe il caso di affrontare i problemi uno alla volta, altrimenti faccio un casino mentale...

Innanzitutto ho trovato una notazione di tipo [] e dei metodi chiamati push e pop.
Tutto questo mi sa di Array...
Andiamo a vedere le proprietà e i metodi degli Array in Javascript...

Sì, come per i comandi Assembly per lo stack, push e pop aggiungono e tolgono dalla coda dell'Array gli elementi.

Provo a crearmi un codice ad hoc...

<script>

var matrice=[]
function aggiungi(nome){
 matrice.push(nome);
}
function elimina(){
 matrice.pop();
}
aggiungi("mario");
aggiungi("pasquale");
aggiungi("antonio");
aggiungi("nicola");
aggiungi("giorgio");
aggiungi("carletto");
for (n=0;n<matrice.length;n++){alert(matrice[n]);}
elimina();
for (n=0;n<matrice.length;n++){alert(matrice[n]);}
elimina();
for (n=0;n<matrice.length;n++){alert(matrice[n]);}
</script>
Sì, funziona come previsto.
Ma i metodi push e pop restituiscono anche dei valori.
Mi faccio un codice che mi aiuta a capire meglio questo:
<script>

var matrice=[]
//il metodo push restituisce la nuova lunghezza dell'Array
alert(matrice.push("mario"));
alert(matrice.push("pasquale"));

//il metodo pop restituisce il nome dell'elemento eliminato dall'Array
alert(matrice.pop());
</script>
Ecco, come mi aspettavo, ottengo prima 1 e poi 2, quindi ottengo il nome "pasquale", che è appunto quello che era in coda ed è stato eliminato.
Quindi si può dichiarare un Array semplicemente con due parentesi quadre!
Questo non lo sapevo...

Dunque la sintassi matrice=[] equivale a quella che già conosco:
<script>

var matrice=new Array();
//il metodo push restituisce la nuova lunghezza dell'Array
alert(matrice.push("mario"));
alert(matrice.push("pasquale"));

//il metodo pop restituisce il nome dell'elemento eliminato dall'Array
alert(matrice.pop());
</script>
o a questa:
<script>

var matrice=new Array("pippo","ciccio","marco","giovanni");
//il metodo push restituisce la nuova lunghezza dell'Array
alert(matrice.push("mario"));
alert(matrice.push("pasquale"));

//il metodo pop restituisce il nome dell'elemento eliminato dall'Array
alert(matrice.pop());
</script>