domenica 21 maggio 2017

L'Ereditarietà Nella Programmazione A Oggetti

In informatica l'ereditarietà è uno dei concetti fondamentali nel paradigma di programmazione a oggetti. In generale, essa rappresenta un meccanismo che consente di creare nuovi oggetti che siano basati su altri già definiti.

Si definisce oggetto figlio (child object) quello che eredita tutte o parte delle proprietà e dei metodi definiti nell’oggetto padre (parent object).


 Essa consiste in una relazione che il linguaggio di programmazione, o il programmatore stesso, stabilisce tra due classi. Se la classe B eredita dalla classe A, si dice che B è una sottoclasse di A e che A è una superclasse di B.

A seconda del linguaggio di programmazione, l'ereditarietà può essere ereditarietà singola o semplice (ogni classe può avere al più una superclasse diretta) o multipla (ogni classe può avere più superclassi dirette).
In generale, l'uso dell'ereditarietà dà luogo a una gerarchia di classi; nei linguaggi con ereditarietà singola, si ha un albero se esiste una superclasse "radice" unica di cui tutte le altre sono direttamente o indirettamente sottoclassi o a una foresta altrimenti; l'ereditarietà multipla definisce invece una gerarchia a grafo aciclico diretto.

Un esempio che metta in luce la potenza dell’ereditarietà, in un programma Windows object oriented potrebbe avere come oggetto fulcro le finestre associate al programma stesso. Supponiamo, ad esempio, che tale software utilizzi, in totale, 100 finestre differenti, visualizzabili a secondo del contesto in cui sta navigando l’utente.
Se, un giorno, si volesse inserire un campo comune a tutte le finestre del programma, in che modo sarà bene procedere? Se non avessimo utilizzato la potenza dell’ereditarietà l’unica strada percorribile sarebbe quella di andarsi a prendere una per una tutte le definizioni delle finestre e inserire il nuovo campo.
Se, invece, si fosse utilizzato in maniera efficiente il paradigma Object Oriented, definendo una classe FinestraBase contenente tutte le caratteristiche comuni ad ogni finestra e derivando da tale classe tutte le finestre in gioco nel programma, allora la modifica sarebbe banalmente quella di inserire il nuovo campo nella classe FinestraBase. Graficamente:




L'ereditarietà è una relazione di generalizzazione/specificazione: la superclasse definisce un concetto generale e la sottoclasse rappresenta una variante specifica di tale concetto generale. Su questa interpretazione si basa tutta la teoria dell'ereditarietà nei linguaggi a oggetti. Oltre a essere un importante strumento di modellazione, l'ereditarietà ha importantissime ripercussioni sulla riusabilità del software.


Per esempio, data una classe telefono se ne potrebbe derivare la sottoclasse cellulare, poiché il cellulare è un caso particolare di telefono. Questo tipo di relazione viene detta anche relazione is-a ("è-un"): "un cellulare è-un telefono".

Gli oggetti appartenenti a una sottoclasse devono essere in grado di esibire tutti i comportamenti e le proprietà esibiti da quelli appartenenti alla superclasse, in modo tale che usarli in luogo di questi ultimi non alteri la correttezza delle informazioni restituite dal programma. È importante, però chiarire un aspetto importante quando si parla di caratteristiche ereditate. Non sempre, infatti, un determinato metodo definito nella classe padre può produrre risultati corretti e congruenti con tutte le classi figlie.

Ad esempio, supponiamo di aver definito una classe padre denominata Uccello, dalla quale faremo derivare le seguenti classi figlie: Passerotto, Merlo e Pinguino.
Nella classe padre, avremo definito il metodo vola(), in quanto rappresenta un comportamento comune a tutti gli uccelli. In tal modo, secondo quanto si è detto in questo paragrafo, tutte le classi figlie non avranno la necessità di implementare tale metodo ma lo erediteranno dalla classe Uccello. Purtroppo, però, nonostante il pinguino appartenga alla categoria degli uccelli, è noto che esso non è in grado di volare, seppur provvisto di ali.
In questo caso, il metodo vola() definito nella classe Uccello, sicuramente valido per la stragrande maggioranza di uccelli, non sarà utile (anzi, sarà proprio sbagliato) per la classe Pinguino. Come comportarsi in questi casi?
Ogni oggetto derivante da una classe padre ha la possibilità di ignorare uno o più metodi in essa definiti riscrivendo tali metodi al suo interno. Questa caratteristica è nota come overriding.

Utilizzando la tecnica dell’overriding, la classe Pinguino reimplementerà al suo interno il metodo vola(), conservando, comunque, la possibilità di richiamare in qualunque momento, anche il metodo definito nella classe padre. In quest’ultimo caso si parlerà di overriding parziale.

Esempio:

Public Class Impiegato
    private nome as String
    private salario as Double
    private matricola as String
    private anniDiServizio as Integer
    Public Sub New(n As String, s as Double, m as String, ads as Integer)
        nome = n
        salario = s
        matricola = m
        anniDiServizio = ads
    End Sub
    Public Sub incrementaSalario(double percentuale)
        salario *= 1 + percentuale / 100
    End Sub
    Public Sub stampaInfo()
        System.Console.WriteLine (nome + " " + salario + " " + matricola)
    End Sub
    Public ReadOnly Property Nome as String
        Get
         return nome
        End Get
    End Property
    Public AnniServizio as Integer
        Get
         return anniDiServizio
        End Get
    End Property
End Class

Public Class Manager Inherits Impiegato
    Private nomeSegretaria as String
    Public Sub New(n as String, s as Double, m asString, ads as Integer)
        MyBase.New(n, s, m, ads)
        nomeSegretaria = String.empty
    End Sub
    Public Sub incrementaSalario(percentuale as Double)
        ' Aggiunge alla percentuale lo 0.5% per ogni anno di servizio
        Dim bonus as Double = 0.5 * AnniServizio
        MyBase.incrementaSalario(percentuale + bonus)
    End Sub
    Public Property Segretaria as String
        Get
            return nomeSegretaria
        End Get
        Set(ByValue Value as String)
           nomeSegretaria = Value
        End Set
    End Property
End Class

Nessun commento:

Posta un commento