|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2057
|
[java] domandina sui Thread e sulle interfacce
ciao,
i thread mi son da sempre stati abbastanza antipatici e vorrei cercare di farmeli stare più simpatici ho un dubbio che spero possiate togliermi Codice:
class Pesa {
public static void main(String[] args) {
int[][] m = {
{ 1, 2 },
{},
{ 1 } };
Casella c = new Casella();
int id = 0;
for (int[] s: m)
new MioThread(id++, s, c);
}
}
Richiamandola all'interno del for i 3 thread vengono avviati uno dopo l'altro o in concomitanza ? cioè mentre è avviato il primo thread parte il secondo o prima di partire il secondo deve finire il primo ? altra domandina : Codice:
((MioThread)Thread.currentThread()).mioId(); E ora una domandina sulle interfacce ! mi son sempre chiesto l'utilità delle interfacce , cioè se un'interfaccia contiene solo la dichiarazione dei metodi e nelle classi che la implementano questi metodi vanno definiti che vantaggio c'è ad usarli ? A cosa servono ? scusate le troppo domande |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Non farti intimorire, i Thread sono tra gli argomenti più semplici che si possano immaginare. Specialmente da quando ci sono i generici
Nel codice che hai incollato i thread non sembrano essere avviati, mancherebbe infatti l'invocazione del metodo start. E' tuttavia possibile che nel costruttore di MioThread tu invochi start() che non è una grandissima idea perché alcune regole del linguaggio Java che riguardano l'inizializzazione dei campi si applicano solo dopo che il costruttore ha terminato l'ultima delle sue istruzioni: l'avvio di un Thread all'interno del costruttore può causare l'esecuzione di codice concomitante alla costruzione. Per capire se effettivamente sia un problema bisogna esaminare il codice nel suo complesso. Supponendo che il metodo start sia invocato, l'avvio dei thread è sequenziale (partono nell'ordine che puoi desumere dal codice del metodo main). La loro esecuzione, cioè quello che capita nei loro metodi run() è concorrente: i thread sono avviati uno alla volta ma ciò che capita nei loro metodi run capita (potenzialmente) nello stesso momento. Per farti un esempio concreto della differenza, se avessimo: Codice:
public class MyThread extends Thread {
private final int id;
public MyThread(int id) {
this.id = id;
System.out.println(id + " E' STATO GENERATO");
}
@Override
public void run() {
System.out.println("IO SONO: " + id);
}
}
Codice:
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
MyThread t = new MyThread(i);
t.start();
}
}
Il metodo Thread.currentThread() restituisce il Thread che sta eseguendo il metodo o l'inizializzatore in cui si trova l'invocazione. Chi sia questo Thread dipenda da tutti fuorché dal metodo in cui ne puoi trovare l'invocazione dal che deduciamo che fare un cast sul suo risultato sia un po' rischioso. Ad esempio: Codice:
void metodo() {
System.out.println(Thread.currentThread());
}
Codice:
new Thread("pippo") {
public void run() {
metodo();
}
}.start()
Codice:
new Thread("pippo") {
public void run() {
metodo();
}
}.start()
Per quanto riguarda le interfacce, in Java esistono per permettere l'ereditarietà multipla - cioè la capacità di un tipo di derivare da più di un tipo dei quali almeno uno non derivato dagli altri. Per ciò che è ereditabile, contengono solo dichiarazioni di metodi perché il fatto di possedere solo le dichiarazioni ma non i corpi esclude la possibilità che si verifichino dei conflitti tra le definizioni di quei metodi. Questi conflitti infatti non possono che essere risolti con regole arbitrarie. Esempio in python: Codice:
class A:
def stampa(self):
print("A")
class B:
def stampa(self):
print("B")
class C(A, B):
pass
a = C()
a.stampa()
Se lasci la firma ma togli il corpo non c'è alcuna regola da applicare: chi eredita eredita il metodo e dovrà dire nel suo corpo cosa voglia fare oppure avrà il corpo dell'unica superclasse da cui può derivare. Dunque interfacce = ereditarietà multipla, solo le firme dei metodi (e quindi non derivazione multipla) perché così non occorre introdurre una regola ad hoc per la risoluzione dell'implementazione del metodo che sarà concretamente invocato. Questo per quanto riguarda le tecnicalità. Per l'altro aspetto delle interfacce, cioè quello per cui chi le implementa dichiara di essere compatibile con il tipo dell'interfaccia, valgono le stesse considerazioni che valgono per le classi.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2057
|
grazie per la risposta sei stato molto gentile e chiaro
il dubbio sui thread è svanito ora sulle interfacce devo rileggere il tutto un pò meglio in quanto ho letto abbastanza di corsa ma la domanda è : se implemento un interfaccia devo definire e implementare tutte le classi dell'interfaccia che andrò ad usare giusto ? allora non era la stessa cosa se definivo ed usavo quella determinata classe senza implementare l'interfaccia ? |
|
|
|
|
|
#4 | ||
|
Senior Member
Iscritto dal: Apr 2003
Città: Genova
Messaggi: 4739
|
Quote:
Quote:
oltre che nel rendere possibile l' ereditarietà multipla come giustamente diceva PGI-Bis, l' utilità dell' interfaccia sta nei casi in cui si faccia uso del polimorfismo quando cioè tu abbia degli oggetti che da una parte ridefiniscano il comportamento di metodi presenti nella classe (base) da cui derivano, ma dall' altra siano usati dal restante codice come istanze della stessa classe base - in questo senso puoi pensare un' interfaccia (che in pratica non è altro che una classe avente metodi tutti virtuali puri) come un contratto, tra il codice di un oggetto che svolge determinate funzionalità e il codice che necessita di quelle funzionalità (ma non necessariamente di sapere "chi" li sta implementando in quel momento, a patto che siano definiti correttamente e il contratto sia rispettato) ti faccio due esempi... in un gioco come poteva essere Diamonds (rip) puoi avere degli oggetti sul campo di gioco (in quel caso gemme normali, gemme "tiled", bauletti) aventi comportamenti differenziati (come sprite generati in modi diversi o animati a differenti intervalli, ma anche e soprattutto diverse reazioni ai metodi crush() o transform() per realizzare la meccanica di gioco) ma anche richiedenti parecchia funzionalità comune (interazione con la griglia e tra loro stesse, ecc) in questo caso conviene avere una classe base che implementi quest' ultima E esponga dei metodi che sicuramente verranno ridefiniti per ogni classe derivata - e infatti avevamo Chest, Gem, BigGem ecc che specializzavano AbstractDroppable (che implementava Droppable) oppure puoi ad esempio realizzare un menu incapsulando il codice corrispondente alle varie opzioni in altrettante implementazioni di uno stesso metodo Codice:
void execute(RunLoop loop) Codice:
selectedMenuAction.execute(this); discorso analogo per la macchina a stati del gioco, dove l' interfaccia GridControllerState era costituita dal metodo Codice:
GridControllerState update(Grid grid, ScoreCalculator scoreCalculator) Codice:
currentState = currentState.update(...);
__________________
Jappilas is a character created by a friend for his own comic - I feel honored he allowed me to bear his name Saber's true name belongs to myth - a Heroic Soul out of legends, fighting in our time to fullfill her only wish Let her image remind of her story, and of the emotions that flew from my heart when i assisted to her Fate
Ultima modifica di jappilas : 25-05-2011 alle 20:05. |
||
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Sì devi implementare tutti i metodi. La seconda domanda non l'ho capita.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2057
|
Quote:
i Codice:
nt pippo (int pesche , String pluto) e nella classe che implementa questa interfaccia devo implementare il metodo pippo facendo : Codice:
class prova implements interfaccia x
{int pippo (int pesche, String pluto)
{implementazione del metodo}
}
Codice:
class prova
{int pippo (int pesche, String pluto)
{implementazione del metodo}
}
|
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Chiarissimo.
Ci sono linguaggi in cui è la stessa cosa - cioè nei quali non useresti l'interfaccia o una superclasse. Java non è tra questi. Dal punto di vista del linguaggio, quando una classe Java "extends" un'altra classe o "implements" una o più interfacce, le istanze di quella classe possono essere usate come argomenti delle invocazioni di metodo o costruttore che dichiarano di volere come tipo di argomento uno qualsiasi dei tipi - classi, interfacce - che la classe, direttamente o indirettamente, implementa o estende. Nell'esempio che fai significa che la "p" di: prova p = new prova(); può essere, ad esempio, usata come argomento dei metodi che richiedono un tipo "x", un tipo "prova" e un tipo java.lang.Object. public void unMetodo(prova a)... public void unMetodo(x a)... public void unMetodo(java.lang.Object a)... è un passpartout. Se la classe prova non implementa l'interfaccia x, pur avendone magari tutti i metodi, non può essere usata come se fosse un tipo di dato x. Ne avrebbe le capacità ma non le manifesta e il compilatore rigetterebbe il tentativo.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Padova
Messaggi: 2342
|
Come ha detto PGI e aggiungo un parere personale:
le interfacce hanno anche un valore "formale" nel definire il comportamento (ovvero i metodi che devono essere forniti) che devono avere determinate classi. Un esempio banale (non del tutto corretto, ma ha senso)... l'interfaccia ADT (abstract data type) può definire i metodi "inserisci" e "estrai". L'interfaccia ADT sarà poi implementata dalle classi Pila, Catena, Albero... infatti le strutture dati Pila, Catena e Albero prevedono tutte metodi di inserimento ed estrazione, anche se ovviamente i metodi saranno implementati in modo diverso a seconda della struttura. Questo è il significato di implementare una interfaccia: la classe che implementa l'interfaccia "si impegna" a fornire determinate funzionalità, nelle modalità specifiche previste dalla classe. In realtà ci sono alcuni casi particolari in cui per il compilatore ha senso richiedere che venga implementata una interfaccia, per esempio nel caso dell'interfaccia Serializable. Una classe implementa Serializable (ma di fatto non deve definire nessun metodo particolare) quando si necessita di inserire gli oggetti istanziati da essa in stream. Ma non è il tuo caso...
__________________
CPU Ryzen 2600 @ 3,95Ghz + Bequiet Dark Rock TF / MB Asus X470-F Gaming / RAM 2x8GB DDR4 G.Skill FlareX 3200 CL14 / VGA Sapphire RX 7900 XT Nitro+ @ 3200Mhz / SSD Samsung 970 Pro 512GB + Sandisk 240GB Plus + Sandisk 960GB Ultra II PSU Seasonic Platinum P-660 / Headset Kingston HyperX Flight |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 23:33.



















