Se ti capisco correttamente, la tua domanda è la seguente: dal momento che usiamo le interfacce per la riusabilità del codice, perché hanno solo metodi astratti? Non ha senso.
La risposta è semplice: le interfacce non sono per la riusabilità del codice .
Allora perché facciamo li usiamo?
Supponiamo di avere tre classi: Dog
, Chicken
e Fish
. Tutti questi estendono la classe Animal
. Tuttavia, mentre Dog
e Chicken
possono essere eseguiti, un Fish
può solo nuotare.
class Dog extends Animal
{
void Run()
{
// how a dog runs
}
}
class Chicken extends Animal
{
void Run()
{
// how a chicken runs
}
}
class Fish extends Animal
{
void Swim()
{
// how a fish swims
}
}
Ora ti chiederò: questo codice è valido?
MakeAnimalRun(Animal animal)
{
animal.Run();
}
No, non lo è. Mentre è perfettamente logico invocare il metodo Run()
per Dog
o Chicken
, non ha senso invocarlo per Fish
, poiché può solo nuotare.
Per poter chiamare il metodo Run()
dell'animale, devo assicurarmi che l'animale possa effettivamente funzionare.
È qui che le interfacce diventano utili. Le interfacce sono utili quando è necessario sapere con certezza che un oggetto ha un comportamento specifico.
Quindi creiamo un'interfaccia chiamata ICanRun
e rendi tutti gli animali che possono eseguire implementarlo :
interface ICanRun
{
void Run();
}
class Dog extends Animal implements ICanRun
{
void Run()
{
// how a dog runs.
}
}
class Chicken extends Animal implements ICanRun
{
void Run()
{
// how a chicken runs.
}
}
E ora questo codice è perfettamente valido poiché sappiamo con certezza che l'animale può correre:
void MakeAnimalRun(ICanRun animal)
{
animal.Run();
}
Si noti che quando parlo di un comportamento, parlo solo della capacità di fare qualcosa, e non di come questa capacità sia effettivamente espressa. Possono essere eseguiti sia Dog
che Chicken
, ma eseguono molto in modo diverso: un Dog
usa 4 gambe mentre un pollo usa solo 2. Quindi l'implementazione del metodo Run()
per il Dog
sarà molto diverso dall'implementazione per Chicken
. Quando definisco questa interfaccia, sono preoccupato per "cosa può fare quell'animale" e non per "come funziona".
Per riepilogare:
Le interfacce non sono per la riusabilità del codice. Le interfacce rappresentano un comportamento a cui un oggetto ha e non interessa il modo in cui implementa questo comportamento. Questo ci permette di sapere con certezza che l'oggetto con cui abbiamo a che fare ha il comportamento che stiamo cercando.