Programmazione basata su classi - Class-based programming

La programmazione basata su classi , o più comunemente orientamento di classe , è uno stile di programmazione orientata agli oggetti (OOP) in cui l' ereditarietà avviene tramite la definizione di classi di oggetti , invece dell'ereditarietà che avviene tramite gli oggetti da soli (confrontare la programmazione basata su prototipi ).

Il modello più popolare e sviluppato di OOP è un modello basato su classi, invece di un modello basato su oggetti. In questo modello, gli oggetti sono entità che combinano stato (cioè dati), comportamento (cioè procedure o metodi ) e identità (esistenza unica tra tutti gli altri oggetti). La struttura e il comportamento di un oggetto sono definiti da una classe , che è una definizione , o progetto , di tutti gli oggetti di un tipo specifico. Un oggetto deve essere creato esplicitamente in base a una classe e un oggetto così creato è considerato un'istanza di quella classe. Un oggetto è simile a una struttura , con l'aggiunta di puntatori al metodo, controllo dell'accesso ai membri e un membro dati implicito che individua le istanze della classe (ovvero gli oggetti della classe) nella gerarchia di classi (essenziale per le funzionalità di ereditarietà di runtime).

incapsulamento

L'incapsulamento impedisce agli utenti di violare le invarianti della classe, il che è utile perché consente di modificare l'implementazione di una classe di oggetti per aspetti non esposti nell'interfaccia senza impatto sul codice utente. Le definizioni di incapsulamento si concentrano sul raggruppamento e impacchettamento delle informazioni correlate ( coesione ) piuttosto che sui problemi di sicurezza. I linguaggi OOP normalmente non offrono restrizioni di sicurezza formali allo stato dell'oggetto interno. L'utilizzo di un metodo di accesso è una questione di convenzione per il design dell'interfaccia.

Eredità

Nella programmazione basata sulle classi, l' ereditarietà viene eseguita definendo nuove classi come estensioni di classi esistenti: la classe esistente è la classe genitore e la nuova classe è la classe figlia . Se una classe figlio ha solo una classe genitore, questo è noto come ereditarietà singola , mentre se una classe figlio può avere più di una classe padre, questo è noto come ereditarietà multipla . Questo organizza le classi in una gerarchia , un albero (se ereditarietà singola) o un reticolo (se ereditarietà multipla).

La caratteristica distintiva dell'ereditarietà è che sia l'interfaccia che l'implementazione vengono ereditate; se viene ereditata solo l'interfaccia, ciò è noto come ereditarietà dell'interfaccia o sottotipizzazione. L'ereditarietà può essere eseguita anche senza classi, come nella programmazione basata su prototipi .

Critica dei modelli di classe

I linguaggi basati su classi o, per essere più precisi, i linguaggi tipizzati , in cui la sottoclasse è l'unico modo per sottotipizzare , sono stati criticati per aver mescolato implementazioni e interfacce, il principio essenziale nella programmazione orientata agli oggetti. I critici dicono che si potrebbe creare una classe bag che memorizzi una raccolta di oggetti, quindi estenderla per creare una nuova classe chiamata classe set in cui viene eliminata la duplicazione degli oggetti. Ora, una funzione che accetta un oggetto della classe bag può aspettarsi che l'aggiunta di due oggetti aumenti la dimensione di una borsa di due, tuttavia se si passa un oggetto di una classe set, l'aggiunta di due oggetti può aumentare o meno la dimensione di una borsa per due. Il problema sorge proprio perché la sottoclassificazione implica la sottotipizzazione anche nei casi in cui non vale il principio della sottotipizzazione, noto come principio di sostituzione di Liskov . Barbara Liskov e Jeannette Wing hanno formulato succintamente il principio in un articolo del 1994 come segue:

Sottotipo Requisito : Sia una proprietà dimostrabile su oggetti di tipo . Quindi dovrebbe essere vero per gli oggetti di tipo where è un sottotipo di .

Quindi, normalmente si deve distinguere sottotipi e sottoclassi. La maggior parte dei linguaggi orientati agli oggetti attuali distingue sottotipi e sottoclassi, tuttavia alcuni approcci alla progettazione non lo fanno.

Inoltre, un altro esempio comune è che un oggetto persona creato da una classe figlia non può diventare un oggetto della classe genitore perché una classe figlio e una classe genitore ereditano una classe persona ma i linguaggi basati sulla classe per lo più non consentono di cambiare il tipo di classe di l'oggetto in fase di esecuzione. Per le lingue basate sulla classe, questa restrizione è essenziale per preservare la vista unificata della classe per i suoi utenti. Gli utenti non dovrebbero preoccuparsi se una delle implementazioni di un metodo provoca modifiche che rompono gli invarianti della classe. Tali modifiche possono essere apportate distruggendo l'oggetto e costruendone un altro al suo posto. Il polimorfismo può essere utilizzato per preservare le interfacce rilevanti anche quando vengono apportate tali modifiche, poiché gli oggetti vengono visualizzati come astrazioni della scatola nera e vi si accede tramite l' identità dell'oggetto . Tuttavia, in genere viene modificato il valore dei riferimenti all'oggetto che fanno riferimento all'oggetto, il che provoca effetti sul codice client.

Lingue di esempio

Sebbene Simula abbia introdotto l'astrazione di classe, l'esempio canonico di un linguaggio basato su classi è Smalltalk . Altri includono PHP , C++ , Java , C# e Objective-C .

Guarda anche

Riferimenti