Che cosa sono le classi astratte e i metodi astratti?

5

Ho ricevuto diverse spiegazioni ma finora non sono in grado di capire che cosa sono le classi e i metodi astratti in Java. Alcuni hanno detto che deve fare qualcosa con la sicurezza del programma, altri hanno detto che non è niente di simile. Anche da Dietel & Il libro di Dietel non ho il suo scopo. Quando, dove e perché lo usiamo?

    
posta Umer Hassan 11.12.2012 - 17:16
fonte

6 risposte

17

Prima di tutto, gli esempi saranno in C #. Ma penso che non avrai problemi a capirlo. Quindi ...

NON PUOI creare un'istanza di oggetti di una classe astratta. Devi avere una sottoclasse che deriva dalla classe, se vuoi istanziarla. Ma questo probabilmente non ti aiuterà poiché potresti averlo già visto prima.

Quindi proviamo con un esempio.

Supponiamo di voler perdere peso e il tuo nutrizionista ti chiede di monitorare l'assunzione di cibo. Quando vai da lei di nuovo, non puoi dirle che hai mangiato un "cibo". Anche se non è sbagliato, dal momento che tutto il cibo ha calorie, è troppo "astratto" per lei. Quindi devi dirle quale cibo.

Quindi, se dovesse codificarlo ... Avrebbe una classe astratta Food.

abstract class Food
{
    public int CaloriesPerPound { get; set; }
    //...
}

Perché? Perché questo non ti permetterebbe di dire "Ho mangiato un cibo".

{
    Food fries = new Food(); //This won't even compile
}

Quindi hai bisogno di lezioni concrete:

class Fruit : Food
{
 //Other stuff related only to fruits
}

class Bread : Food
{ 
 //Other stuff related only to Bread
}

Quindi dovrai dire esattamente quale cibo è.

{
   Apple desert = new Apple(); //Now we are talking
}

Ma lei ha ancora bisogno della lezione di cucina, è comunque interessante per lei:

class Meal
{
    public List<Food> Foods { get; set; }
    //Other meal related stuff
    public int TotalCalories()
    {
        int calories = 0;
        foreach (Food food in Foods)
        {
            calories = calories + food.CaloriesPerPound * FoodQuantity;
        }
        return calories;
    }
}

Questo è un esempio di quando hai bisogno di una classe astratta. Quando vuoi avere una classe base, ma non vuoi che qualcuno crei un oggetto della tua classe.

Una CAN astratta ha metodi astratti. Non è necessario. È assolutamente ok avere una classe astratta senza metodi astratti. A proposito di ...

Il metodo astratto è qualcosa che è troppo ampio. Non ci sono somiglianze su come funzionano le cose, quindi le classi che derivano dalla tua classe che ha un metodo astratto non saranno in grado di chiamare l'implementazione di super-classe. E stai anche costringendo tutte le sottoclassi a implementare la loro versione di quel metodo.

Proviamo un altro esempio? Un simulatore di bande animali. Avresti degli animali e ognuno di loro emetterebbe un suono. Ma queste sono "implementazioni" molto diverse, non hanno nulla in comune. Un cane è diverso da un gatto, un gatto da un elefante, un elefante da un cricket. Quindi avresti un metodo astratto MakeSound.

class Animal
{
    public abstract void MakeSound();
}

Ma, se hai un metodo astratto nella tua classe, ciò rende l'intera classe astratta!

abstract class Animal
{
    public abstract void MakeSound();
}

Quindi il resto del codice potrebbe essere:

class Dog : Animal
{
    public void MakeSound()
    {
        //bark at the moon
    }
}

class Cat : Animal
{
    public void MakeSound()
    {
        //meowing for food
    }
}

E la BAND!

class AnimalBand
{
    public List<Animal> Animals { get; set; }
    public void RockOn()
    {
        foreach (Animal animal in Animals)
        {
            animal.MakeSound();
        }
    }
}

Quindi questo è un esempio di quando usi un metodo astratto.

Credo che questa sia l'essenza. Potrebbe essere un po 'forzato / contorto, ma penso che dia il merito. Torna agli esempi che non ti hanno aiutato prima e vedi se hanno senso ora.

Io esco su un ramo e dico che sei un principiante. Questa roba può sembrarti strana e potresti non notare alcun vantaggio nell'uso di classi astratte.

Va bene. È strano per quasi tutti noi quando iniziamo. Ma col tempo imparerai ad apprezzarlo.

    
risposta data 11.12.2012 - 18:32
fonte
5

Una classe astratta è una classe che non può essere istanziata (cioè new myAbstractClass() ). Viene utilizzato come modello per altre classi all'indirizzo inherit .

Un metodo astratto è un metodo in una classe astratta che può essere sovrascritto (cioè implementato) in una classe derivata.

La differenza tra interface e abstract class è che puoi mettere funzionalità in una classe astratta (cioè metodi ordinari o virtuali) che possono essere utilizzati nella classe derivata, mentre un'interfaccia è solo un modello vuoto.

    
risposta data 11.12.2012 - 17:25
fonte
2

Con le classi astratte puoi avere una sorta di scheletro per le altre classi da estendere.

Non puoi istanziarle ma puoi mettere alcune implementazioni comuni che puoi usare nelle classi che le estendono.

    
risposta data 11.12.2012 - 17:28
fonte
2

Una classe astratta è una classe che implementa alcune funzionalità comuni utilizzate da una o più classi concrete (non astratte).

Un buon esempio di questo sarebbe la classe AbstractList in Giava. Questa classe è estesa da ArrayList (una classe concreta) e AbstractSequentialList (una classe astratta a sua volta estesa da LinkedList ).

Uno non istanzia mai un AbstractList (quale vuoi? ArrayList? Vector? LinkedList?) e quindi è reso astratto per prevenire questo. Tuttavia, implementa alcuni componenti interni necessari per il funzionamento di un elenco (conteggio delle modifiche per il fail veloce).

Un metodo astratto è un metodo che non è implementato in una classe astratta o in un'interfaccia, ma deve essere implementato nella classe concreta.

Il motivo principale per cui si vorrebbe che un metodo fosse astratto è far parte di un'API pubblica. Se il metodo compareTo in Comparable è astratto, solo la classe concreta sa come implementarla correttamente per le altre classi da chiamare.

    
risposta data 11.12.2012 - 17:37
fonte
1

Una classe astratta / metodo è, concettualmente, un "punto di partenza" per un'implementazione concreta.

Un metodo astratto o un altro membro non possono avere alcun codice; è letteralmente un segnaposto per un membro che deve essere implementato da classi derivanti dalla base astratta. È simile a una dichiarazione di metodo in un'interfaccia, ma una classe astratta può definire membri astratti di qualsiasi visibilità ereditabile, non solo pubblica. Quel membro astratto può essere usato in qualsiasi codice della classe astratta. Lo scopo è di solito consentire alla classe derivante di specificare una logica o un comportamento specifici dell'implementazione, la cui estrazione dal codice circostante rende indipendente l'implementazione del codice rimanente.

Una classe astratta non può essere istanziata; esiste da derivare e da utilizzare come tipo comune per membri e parametri, simile a un'interfaccia in questo senso. Le classi con membri astratti devono essere contrassegnate come astratte, ma una classe senza membri astratti può anche essere contrassegnata come astratta. Pertanto, le classi astratte possono avere codice in membri non astratti, che è la differenza principale da un'interfaccia (l'altra differenza chiave è la capacità di definire membri astratti meno visibili di "pubblico"). Questa è una tattica comune per condividere (e quindi riutilizzare) il codice che è comune tra le implementazioni della classe astratta.

Per quanto riguarda il momento in cui usarli, in modo succinto, usa una classe astratta ogni volta che utilizzi normalmente un'interfaccia, ma quando desideri anche definire un codice che possa essere condiviso tra le implementazioni derivate della base.

Esistono diverse best practice tra Java e C # relative alla combinazione di interfacce e abstract nella stessa gerarchia di ereditarietà. È stata la mia esperienza che un'interfaccia implementata direttamente da una singola classe astratta è ridondante in Java a causa delle convenzioni di denominazione (i nomi delle interfacce dovrebbero assomigliare ai nomi delle classi, così i programmatori non devono preoccuparsi di cosa stanno usando). In C #, il pattern è ancora considerato un po '"profondo" ma è più accettabile perché l'interfaccia, per convenzione, sarebbe preceduta da "I-". In entrambi i casi, la disposizione consente anche di rifattorizzare o sostituire la classe astratta senza influenzare le classi dipendenti; non solo è possibile utilizzare qualsiasi implementazione di DoerBase astratto, ma qualsiasi Doer (o IDoer) che includa un'implementazione di un nuovo BetterDoerBase o una classe concreta ereditata direttamente dall'interfaccia.

    
risposta data 11.12.2012 - 19:00
fonte
0

Un esempio di vita reale di una classe astratta potrebbe essere Umano per esempio. Ma intesti un oggetto Human ? No! Otterrai inoltre lezioni dalla classe astratta umana come Infant , Bambino , Adulto , Man , Donna , ecc. E estendere / restringere il comportamento originale in queste classi derivate giù nella gerarchia.

    
risposta data 11.12.2012 - 17:37
fonte