domenica 19 agosto 2012

Thread...che passione!

Oggi parliamo di questi benedetti Thread e di come si implementano in Java. Per prima cosa vediamo la definizione data da Wikipedia: "un thread o thread di esecuzione è una suddivisione di un processo in due o più filoni, che vengono eseguiti concorrentemente dal processore". In sostanza il thread non è altro che un pezzo di processo. Come si implementa il multi-threading  in Java? ossia come gestire più thread in Java? Esistono due vie, tecnicamente entrambe valide, per implementare il multi-threading e cioè attraverso l'implementazione dell'interfaccia  Runnable o creando una classe che estenda la classe Thread.
Nel primo caso scriviamo una nuova classe che implementi l'interfaccia Runnable e assegniamo un istanza di questa classe ad un nuovo oggetto Thread. Ecco un esempio:

public class SayHello implements Runnable {
private String greeting;

public SayHello(String greeting) {
  this.greeting = greeting;
}

public void run() {
 for(int i = 1; i < = 10; i++) {
 System.out.print(greeting);
 }
 System.out.println(“End of run”);
 }
}

è necessario implementare il metodo run in cui inseriremo il codice che dovrà essere eseguito dal Thread. Tutto questo però non rende un oggetto di classe SayHello un oggetto Thread. Occorre associare l'istanza della classe Say Hello con un nuovo oggetto Thread:

public class CountToTen {
public static void main(String [] args) {
   SayHello hello = new SayHello(“Hi”);
   Thread t = new Thread(hello);
   t.start();
   for(int k = 1; k < = 10; k++) {
       System.out.print(k);
   }
   System.out.println(“End of main”);
  }
}

Nel secondo caso creiamo una nuova classe che estende la classe Thread e in cui sovrascriviamo il metodo run:


public class MyThread extends Thread {
 private String message;
 private boolean keepGoing;

 public MyThread(String m) {
   message = m;
   keepGoing = true;
 }

 public void setKeepGoing(boolean b) {
   keepGoing = b;
 }

 public void run() {
     while(keepGoing) {
         System.out.print(message + “ “);
         try {
                Thread.sleep(1000);
         }catch(InterruptedException e) {}
    }
    System.out.println(“gone!”);
 }
}


Ora non sarà più necessario istanziare due oggetti come avveniva con il precedente pezzo di codice:


public class Main {
 public static void main(String [] args) {
    MyThread myThread = new MyThread(“going”);
    myThread.start();
    try {
           Thread.sleep(6000);
     }catch(InterruptedException e) {}
 myThread.setKeepGoing(false);
 System.out.println(“End of main”);
 } 
}

Ma quale dei due metodi conviene usare? Da un punto di vista object-oriented, l'opzione da preferire per scrivere un thread è implementare Runnable. Infatti cosi facendo si crea una giusta separazione tra l'oggetto thread (che sarà schedulato, sincronizzato ecc.) e l'oggetto runnable che contiene il codice eseguito quando il thread è schedulato.

domenica 8 luglio 2012

Question and answer: pre-intervew

Ma come si svolge un colloquio a Londra presso un azienda informatica? Il processo completo lo spiegherò in dettaglio in un post successivo ma in questo vi fornisco un piccolo suggerimento. L'azienda appena approccia un potenziale candidato, effettua un primo test ponendo diversi quesiti. Questi servono a capire se il candidato ha le basi e se può partecipare ad una interview face to face.Ad esempio per un ruolo come java developer le domande potrebbero essere queste:


1)      What blogs, publications, and websites do regularly you use to keep up to date with the latest technologies? Do you actively contribute to any of them?



2)      In the following example, which features of the Java language are illustrated in (a) methodOne’s parameter list, and (b) the ‘for’ loop?
   class MyNewClass {
       public static void methodOne(String s, String t, Integer ... ii) {
              for(int jj : ii) {
                     System.out.print(jj + " " + s + " " + t);
              }
       }
   }



     3)      Our clients operate in a global market, therefore our applications must operate in many different countries.  Name two basic data types whose format varies between countries, that software must account for.
      4)      Simplify the following section of code.
   public void showCollection (Collection collection) {
         Iterator ii = collection.iterator();
         for(int kk = 0; kk < collection.size(); kk++) {
                 MyClass one = (MyClass) ii.next();
                 one.printResult();
         }
   }


      5)      What feature of the Java programming language is the following code an example of? If you’ve used the feature to solve a problem, please give an example.
   Class c = Class.forName("java.lang.String");
   Method m[] = c.getDeclaredMethods();
     6)      What type of design pattern is this? Can you name one or more potential issues with this pattern?
   public class MyObject {
       private static final MyObject INSTANCE = new MyObject();
private MyObject () {}
public static MyObject getInstance() {
return INSTANCE;
   }
   }


    Sei pronto per questo tipo di domande?

sabato 30 giugno 2012

Volatile: cosa vuol dire in Java?

Spesso accade durante una interview che venga chiesto cosa sia e cosa voglia dire la keyword "volatile" in Java. Questa parola è usata per indicare ad un Thread di non memorizzare il valore di una variabile nella cache ma direttamente nella memoria principale. Perché? Ora immaginiamo che il Thread A modifichi il valore della variabile "pippo". Se il Thread B deve leggere il valore di tale variabile potrebbe accadere che il suo valore non sia stato ancora aggiornato con le modifiche di A. Con la parola chiave volatile si forza il Thread A a rendere visibili gli aggiornamenti fatti immediatamente.
Ora proviamo a vedere un esempio.


public class Singleton{private static volatile Singleton _instance;
public static Singleton getInstance(){
   if(_instance == null){
            synchronized(Singleton.class){              

              if(_instance == null)
                  _instance = new Singleton();
            }
   }
   return _instance;
}



Se non rendiamo la variabile _instance volatile allora il Thread che sta creando l'istanza di "SIngleton", non è in grado di comunicare a gli altri Thread che l'istanza è stata creata fino a che non finirà l'esecuzione del blocco singleton; quindi se il A sta creando un istanza di Singleton e appena dopo la creazione perde la CPU allora tutti gli altri Thread non saranno in grado di vedere il valore della variabile _instance come non nullo e crederanno che il suo valore sia ancora null.
Infine da ricordare che la parola chiave volatile è valida solo per le variabili. Questa differenzia la parola chiave volatile dalla parola chiave synchronized. 

venerdì 15 giugno 2012

Java ecologico: le variabili d'ambiente e il CLASSPATH


Quando si parla di compilazione di codice Java sicuramente vi sarà capitato di sentir parlare di variabili d'ambiente e CLASSPATH. Il classpath si riferisce al percorso sul tuo file system dove i tuo file .class sono salvati. Il classpath è definito dalla variabile d'ambiente CLASSPATH. Il CLASSPATH specifica le directory e i file JAR dove il compilatore e la JVM troveranno il bytecode. Attraverso l'utilizzo del CLASSPATH si permette di memorizzare il bytecode in directory a nostra scelta o in archivi Java (JAR File).

Rendi ecologico il tuo pc con le variabili d'ambiente..


Per esempio supponiamo di avere la classe com.bustapaga.Impiegato. Il compilatore e la JVM cercheranno la directory \com\bustapaga basandosi sulla variabile d'ambiente CLASSPATH. Quindi se per esempio il file Impiegato.class si trova nella directory

c:\Documents and Settings\Alex\workspaces\build\com\bustapaga

allora la variabile CLASSPATH deve includere la directory

c:\Documents and Settings\Alex\workspaces\build

La variabile CLASSPATH può contenere un qualsiasi numero di directory e file JAR.

Ma come settare questa variabile d'ambiente? Dipende ovviamente dal sistema operativo.

Sotto un sistema Windows: aprire il prompt dei comandi e settare la variabile classpath con questa istruzione (separando i multi valori con il punto e virgola)

set CLASSPATH=”c:\Documents and Settings\Alex\workspaces\build”;
c:\myproject\build;c:\tomcat\lib\servlet.jar;.;

Sotto un sitema Unix: usare il comando setenv per separare valori multipli

setenv CLASSPATH /usr/build:/myproject/build:/tomcat/lib/servlet.jar

Attenzione! Un errore comune da evitare è quello di includere parte del nome del percorso del package nella variabile CLASSPATH. Da evitare ad esempio un errore simile:

set CLASSPATH=c:\myproject\build\com\bustapaga;

mercoledì 13 giugno 2012

Che tipi! Primitive Types vs. Reference Types


Le applicazioni Java prevedono due tipi di dati: primitivi e referenziati. I tipi primitivi sono i classici tipi di dati che si imparano sin dalle prime lezioni di programmazione e sono riassunti nella tabella qui sotto.



La tabella mostra anche i diversi range di valori permessi per ogni tipo. Difficile ricordare ogni singolo range mentre può essere molto utile ricordare la dimensione in bits prevista per ogni tipo.

Un Reference type invece, sono variabili che sono tipi di classe, tipi di interfacce o tipi di array. Una "reference" fa riferimento a un oggeto (un istanza di una classe). A differenza dei tipi primitivi che mantengono i loro valori im memoria dove la variabile è allocata, le referenze non mantengono il valore dell'oggetto a cui si riferiscono. Una referenza "punta" ad un oggetto memorizzando l'indirizzo dove l'oggetto è collocato. Tutto questo può essere ricondotto al conetto di "puntatore". Tuttavia Java non permette al programmatore di accedere direttamente ad un indirizzo fisico di memoria. Quindi anche se le referenze sono simili ai puntatori, è possibile solo usare una referenza per accedere ad un campo o un metodo dell'oggetto a cui fa riferimento. Risulta impossibile quindi determinare il reale indirizzo di memoria della variabile referenziata.
Vediamo un esempio ora. Dichiariamo due referenze:

java.util.Date today;
String greeting;

La variabile today è una refernza di tipo Date e può puntare solo a un oggetto di tipo Date. La variabile greeting invece è una referenza che può puntare solo ad un oggetto di tipo String. Un valore può essere assegnato ad una referenza in due modi:
- Una referenza può essere assegnata ad una referenza dello stesso tipo
- Una referenza può essere assegnata ad un nuovo oggetto usando la parola chiave "new"

Ad esempio assegnamo le due precedenti referenze a due nuovi oggetti:

today = new java.util.Date();
greeting = “How are you?”;

Ecco come queste due referenze sono rappresentate in memoria:

martedì 8 maggio 2012

Sviluppo "guidato": il Test Driven Development

Il test driven development (TDD) è una pratica agile che richiede la creazione di test prima della scrittura del codice sorgente stesso da testare. In realtà è una metodologia utilizzata non per testare il codice, bensì per individuare con precisione le specifiche del software stesso. Ma come avviene questa tipologia di sviluppo? Come mostrato nella figura 1 la prima cosa da fare è quella di creare un test. Il secondo passo consiste nell'eseguire il test. Ovviamente non essendo ancora stato scritto codice per quel test, l'esecuzione del test comporta un fallimento. Occorre quindi apportare delle modifiche al codice in modo che il test sia superato e una volta che ciò avviene si continua con lo sviluppo.

Figura 1. Diagramma sviluppo TDD

Vediamo ora un esempio semplice di codice:


-          Aggiungiamo il test

public void NumberToEnglishShouldReturnOne()
{
  string actual = English.NumberToEnglish(1);
  Assert.AreEqual("one", actual, "Expected the result to be \"one\"");
}

-          Eseguiamo il test. Il test fallisce in quanto il codice non è stato ancora implementato
"NumbersInWords.Test.EnglishTest.NumberToEnglishShouldReturnOne :
    System.Exception :
The method or operation is not implemented.".

-         Scriviamo il codice in modo che il test sia superato
public static string NumberToEnglish(int number)
{
  return "one";
}

-          Eseguiamo di nuovo il test
-          Una volta che il test è passato il prossimo passo è iniziare di nuovo il processo (code refactoring)

Ad esempio il nuovo test sarà:
public void NumberToEnglishShouldReturnTwo()
{
  string actual = English.NumberToEnglish(2);
  Assert.AreEqual("two", actual, "Expected the result to be \"two\"");
}

Quindi modifichiamo il codice in modo che il test sia passato:

public static string NumberToEnglish(int number)
{
  if (number == 1)
    return "one";
  else
    return "two";
}



Ma quali sono i vantaggi di questa metodologia? Il codice. può essere testato singolarmente, sono individuate con precisione le specifiche del codice e sicuramente permette di individuare con facilità lo stato di avanzamento del progetto. Per ulteriori informazioni sul TDD date un'occhiata a questa pagina.

mercoledì 25 aprile 2012

Android e i grafici: GraphView

Mi è capitato l'altro giorno, lavorando a un progetto personale, di dover mostrare dei grafici su alcuni dati memorizzati in un database sqlite. Android non offre nativamente la possibilità di usare i grafici ma esistono diverse librerie Java utilizzabili in Android. Molto interessante ho trovato la libreria GraphView di Jonas Gehring, facile da usare e abbastanza funzionale. Permette la creazione di grafici semplici come line chart e bar chart ma anche qualcosa di complesso come le serie multiple.
Vediamo ora un pezzo di codice che utilizza questa libreria.

Codice Java:


GraphViewData[] data = 
        new GraphViewData[data_from_db.size()];
       double v=0;
       for (int i=0; i<data_from_db.size(); i++) {
data[i] = new GraphViewData(i, data_from_db.get(i));
       }
GraphViewSeries exampleSeries= new GraphViewSeries("Sinus curve", Color.rgb(200, 50, 00), data);
GraphView graphView = new LineGraphView(this, "GraphViewDemo");
graphView.addSeries(exampleSeries); // data
graphView.setScrollable(true);
graphView.setHorizontalLabels(regioni);
graphView.setScalable(true);  
LinearLayout layout = (LinearLayout) findViewById(R.id.graph1);
layout.addView(graphView);
File Xml: 
<?xml version="1.0" encoding="utf-8"?>
<ScrollView android:id="@+id/ScrollView02" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
              xmlns:android="http://schemas.android.com/apk/res/android">
<HorizontalScrollView 
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="2000dip"
android:layout_height="500dip"
android:id="@+id/graph1" />
<TextView  
   android:id="@+id/legend"
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
android:textColor="#ffffff"
android:textSize="17sp" 
    />
  </LinearLayout>
    </HorizontalScrollView>
</ScrollView>

Il codice crea un serie a partire dal vettore data_from_db contenente i dati che vogliamo mostrare nel nostro grafico. Successivamente crea un oggetto di tipo GraphView che rappresenterà il nostro grafico e assegna a tale oggetto la serie creata in precedenza. Infine aggiunge il grafico al LinearLayout definito nel file xml.
Questo è il risultato ottenuto.



Una libreria facile da usare che offre diverse opzioni per rendere più gradevoli ed espliciti i propri grafici su Android. Per maggiori  informazioni consultare il blog ufficiale della libreria.

martedì 24 aprile 2012

Il plurale di Http? Https!

Ecco un'altra classica domanda che ti capita, cosi per caso, ad un colloquio di lavoro. Che differenza c'è tra http e https? Diamo per scontato che sappiamo di cosa parliamo (protocolli) e che già siamo al corrente dell'esistenza del protocollo http. Che differenza c'è con il protocollo Https? la differenza la fa la S finale che sta per "secure". Si, il protocollo https è un'evoluzione di Http per renderlo più sicuro. In particolare è una combinazione del protocollo Http e il protocollo SSL/TLS. Il problema principale del protocollo Http è la possibilità di subire attacchi del tipo Man in the middle (un tipo di attacco dove l'attaccante è in grado di intercettare le comunicazioni tra i due partecipanti).


Https agisce sempre al livello più alto del modello ISO/OSI. Tutti i dati sono criptati compresi gli header. Un webserver per accettare connessioni di tipo Https deve creare un certificato digitale una sorta di carta di identità che associa l'identità di una persona ad una chiave pubblica. Una volta che il sito web ha fornito questo certificato che prova la sua bontà, il protocollo SSL/TLS è più che sufficiente a criptare il canale di comunicazione tra utente e sito web. I certificati sono approvati da specifiche certificate authorities (ad esempio VeriSign/Microsoft/etc.).

lunedì 9 aprile 2012

Riflettiamo con la Java Reflection

L'idea di questo post nasce da un test preselezione che ho fatto per un'azienda inglese. Dato un pezzo di codice veniva chiesto quale caratteristica del linguaggio Java era utilizzata. Si trattava della reflection.

La reflection è quella caratteristica del linguaggio Java che permette ad un programma  in esecuzione di accedere a proprietà interne del programma stesso. Tutto ciò ovviamente in contro tendenza con il paradigma orientato agli oggetti. Ad esempio con questa caratteristica è possibile per un classe Java ottenere e accedere al nome di tutti i suoi metodi e attributi ed eventualmente mostrarli.

Perché la reflection?

La violazione del principio di incapsulamento dei linguaggi object oriented può essere pericoloso ma se trattato con le giuste accortezze diventa uno strumento potentissimo. In particolare può essere utile nei framework e in casi in cui si necessità di un forte riutilizzo di codice. Consideriamo ora un esempio di codice Java (fonte sito ufficiale della Oracle):


   import java.lang.reflect.*;
 
   public class DumpMethods {
      public static void main(String args[])
      {
         try {
            Class c = Class.forName(args[0]);
            Method m[] = c.getDeclaredMethods();
            for (int i = 0; i < m.length; i++)
            System.out.println(m[i].toString());
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }


Per usare la reflection occore effettuare l'import del package java.lang.reflect.Ora richiamando la classe DumpMethods e passando come input la stringa "java.util.Stack" l'output che otteniamo è il seguente:


 public java.lang.Object java.util.Stack.push(
    java.lang.Object)
   public synchronized 
     java.lang.Object java.util.Stack.pop()
   public synchronized
      java.lang.Object java.util.Stack.peek()
   public boolean java.util.Stack.empty()
   public synchronized 
     int java.util.Stack.search(java.lang.Object)



otteniamo quindi l'elenco dei metodi della classe Stack compreso di parametri e il tipo restituito da ogni metodo.

Un ottimo esempio di come sia utile la reflection è nella conversioni di documenti XML in oggetti Java (più facilmente manipolabili all'interno di un applicazione scritta in linguaggio Java). Trovate un ottimo esempio di codice qui.

Infine per una illustrazione completa dei diversi usi della reflection date anche un'occhiata qui.

Eccomi di nuovo: qui London!

Eccomi di nuovo online! Ok la connessione internet ce l'ho da un pezzo qui a Londra ma era il tempo che mi mancava! Ora torno a scrivere nuovi post sul mio blog direttamente live from London!

Sono alla ricerca di un lavoro come informatico qui a Londra e devo dire che la vita è abbastanza dura. Ho fatto già un paio di colloqui e devo dire che sono abbastanza duri! Però spero di farcela il prima possibile. Per questo nel fra tempo mi sono trovato un lavoretto part-time anche per migliorare il mio inglese. Lavoro da Eat. Se passate qui da Londra vi consiglio di pranzare in uno di questi deliziosi negozietti.

Ora provvedo a pubblicare nuovi post e magari prossimamente pubblicherò qualche aggiornamento sui miei colloqui di lavoro e su come si svolgono qui a Londra.

See you soon!


mercoledì 8 febbraio 2012

Interview question: Repository Pattern e Factory Pattern

Oggi parleremo di Repository Pattern e Factory Pattern. Entrambi fanno parte della categoria dei Design pattern ossia quell'insieme di schemi di progettazione che permettono di risolvere problemi riccorrenti. Esistono diversi tipi di pattern che sono classificati in base a diversi criteri. Solitamente si sceglie di classificare i pattern a seconda del problema che trattano.
In questo post tratteremo due pattern in particolare: il Factory Pattern e il Repository Pattern. Il Factory Pattern rientra nella categoria dei "pattern creazionali" ossia tutti quei pattern che si nascondono i costruttori delle classi "camuffandoli" con metodi in modo che si possano utilizzare gli oggetti senza sapere come siano utilizzati (un po' come fanno le interfacce). Questo pattern aiuta a modellare un interfaccia per la creazione di un oggetto il quale nel momento in cui viene creato può permettere alle sue sottoclassi di decidere quale classe instanziare.



Questo pattern, come mostrato in figura, è usato quando la classe Creato non conosce in anticipo tutte le sue sottoclassi che andrà a creare. Invce è lasciata ad ogni sottoclasse, la ConcreteCreator, la responsabilità della creazione dell'istanza dell'oggetto corrente.

Il Repository Pattern fa parte dell'insieme dei pattern architetturali che non operano a livello di design e quindi non sono considerati veri e propri pattern. Questo pattern vuole evitare l'accesso diretto alle fonti dati come database, servizi web, liste sharepoint ecc. in quanto questo comperterebbe diversi problemi come codice duplicato, alto rischio di errori di programmazione, tipizzazione debole dei dati di business e cosi via. Cosa propone questo pattern? L'utilizzo di un repository per separare la logica di ritrovamento dei dati dalla logica di bussiness.


In questo modo la logica di bussiness e il data source non comunicano direttamente ma lo fanno solo attraverso i repository come mostrato in precedenza nella figura.


Si parte! Destinazione London!

Finalmente si parte. Il 22 febbraio sbarcherò a Londra (anche conosciuta come L'ondra) per dare inizio alla mia avventura. Avventura, di questo si tratta. Partirò per andare a cercare lì un lavoro nel mondo nell'informatica e realizzare il mio sogno: informatico inglese :-)
Sicuramente sarà un'avventura difficile e speriamo lunga. Sicuramente nei prossimi mesi l'esperienza mi cambierà. Speriamo in bene. Ho bisogno di una nuova sfida. Ho bisogno di stimoli. Ho bisogno di migliorare. Quale città meglio di Londra per iniziare!
Mi fermo qui e magari successivamente farò un post sulle emozioni che si provano nel pensare, organizzare ed iniziare questa avventura (magari appena arrivato a Londra).

Se mai un giorno qualcuno leggerà questo post, vedendo dove mi troverò in quel momento, capirà che io ci ho davvero creduto dall'inizio!


venerdì 27 gennaio 2012

Fai socializzare la tua app!

Ho scoperto di recente lavorando su una mia applicazione android un servizio davvero interessante. Il suo nome è socialize e permette di rendere la tua applicazione android o iOS più "sociale". In pratica è resa disponibile un Api gratuita che permette di aggiungere una barra contente diverse opzioni che rendono social l'app. Queste opzioni sono il classico "I like" stile facebook, un contatore delle visualizzazioni, la possibilità di condivisione del contenuto via facebook, email o sms e la possibilità di lasciare un commento anonimamente o loggandosi con il proprio account facebook. Ovviamente è possibile utilizzare anche il proprio account twitter invece dell'account di facebook.


Il servizio è gratuito se il traffico coinvolge meno di 100.000 utenti. Superate tale soglia occore comprare uno dei vari account premium proposti.
Ho inserito tale servizio nella mia applicazioni in quanto mi ha permesso in pochissimi passi di dare un aspetto social, che è tanto in voga oggi e comunque utile, alla mia applicazione.

Get Socialize!

giovedì 26 gennaio 2012

La storia di Android in 2 minuti


Ecco per voi un'immagine (fonte: http://www.xcubelabs.com) che riassume in 2 minuti tutta la cronologia delle varie versioni di Android dalla sua nascita ad oggi:



Perché le interfacce?

Molti si saranno chiesti a cosa servono e se sono realmente utili le interfacce software. Cercheremo di spiegarlo brevemente in questo post.

Un'interfaccia altro non è che una porzione di software che permette di interagire con le risorse hardware (memoria, CPU e cosi via) che si trovano ai livelli sottostanti. L'accesso a queste risorse se lasciato libero e indiscriminato può portare a diversi incovenienti. Per questo si può permettere l'accesso a tali risorse solo attraverso precisi entry point, ad esempio le interfacce.

Ma cosa è un'interfaccia nel campo della programmazione ad oggetti? Altro non è che una classe che non contiene dati, quindi di tipo astratto, e può contenere quindi solo metodi d'istanza astratti ( non può contenere né costruttori, né variabili di istanza, né metodi statici ecc.). Tuttavia una classe può implementare più interfacce. Una volta che una classe implementa un'interfaccia, il compilatore sà che un'istanza della classe conterrà lo specifico insieme di metodi. Per spiegare meglio cosa sia un'interfaccia usiamo un'analogia: un interfaccia seriale su un computer definisce un insieme di pin assegnati e il controlo dei segnali che saranno usati; il dispositivo può essere usato per differenti task: mouse, modem, ecc. e questi saranno tutti controllati attraverso lo stesso meccanismo di istruzioni digitali. Per cosa può essere utile un'interfaccia? Se una classe ha bisogno di due differenti insiemi di metodi cosi che il suo comportamente sia  quello di due cose differenti, può ereditare un insieme dalla classe A e usare un'interfaccia B per specificare l'altro!