{"id":1199,"date":"2009-12-11T11:50:54","date_gmt":"2009-12-11T10:50:54","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=1199"},"modified":"2010-04-27T13:53:05","modified_gmt":"2010-04-27T11:53:05","slug":"l009-programmazione-orientata-agli-oggetti-oop","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/l009-programmazione-orientata-agli-oggetti-oop\/","title":{"rendered":"L#009 &#8211; Programmazione Orientata agli Oggetti (OOP)"},"content":{"rendered":"<p>Con l&#8217;articolo di oggi non intendo scrivere un trattato sulla teoria della programmazione ad oggetti, non ne sarei capace e gli scaffali delle librerie sono pieni di libri su questo argomento\u2026vorrei invece, con l&#8217;aiuto di qualche esempio, far vedere come i pilastri della OOP vengono implementati in objc e come la conoscenza di questi concetti basilari sia indispensabile per interpretare correttamente le guide fornite da Apple.<br \/>\nMa quali sono questi pilastri della OOP? Sono l&#8217;<em>ereditariet\u00e0<\/em>, l&#8217;<em>incapsulamento<\/em> ed il <em>polimorfismo<\/em>, vediamo brevemente cosa sono e come applicarli creando una nostra classe inventata, la classe &#8220;<em>persona<\/em>&#8220;.<!--more--><\/p>\n<p>Creiamo una nuova classe cliccando sul men\u00f9 file-&gt; new file e selezionando dalla categoria &#8220;cocoa touch class&#8221; l&#8217;icona obiettive-c class. Notiamo la voce &#8220;subclass of: NSObject&#8221; questo significa che la nostra classe erediter\u00e0 direttamente da NSObject, la madre di tutte le classi, se non \u00e8 chiaro lo sar\u00e0 pi\u00f9 avanti quando parleremo di ereditariet\u00e0.<\/p>\n<p>Diamo un nome significativo (&#8220;<em>fraction<\/em>&#8220;) e clicchiamo su ok. I file creati hanno questa sintassi, io li ho arricchiti con due variabili di istanza e 5 metodi:<\/p>\n<pre lang=\"objc\" escaped=\"true\">\r\n\/\/file fraction.h\r\n@interface Fraction: NSObject {\r\n    int numerator;\r\n    int denominator;\r\n}\r\n-(void) print;\r\n-(void) setNumerator: (int) n;\r\n-(void) setDenominator: (int) d;\r\n-(int) numerator;\r\n-(int) denominator;\r\n@end<\/pre>\n<pre lang=\"objc\" escaped=\"true\">\r\n\/\/file fraction.m\r\n@implementation Fraction\r\n-(void) print {\r\n    printf( \"%i\/%i\", numerator, denominator );\r\n}\r\n\r\n-(void) setNumerator: (int) n {\r\n    numerator = n;\r\n}\r\n\r\n-(void) setDenominator: (int) d {\r\n   if (d!=0)\r\n       denominator = d;\r\n}\r\n\r\n-(int) denominator {\r\n    return denominator;\r\n}\r\n\r\n-(int) numerator {\r\n    return numerator;\r\n}\r\n@end<\/pre>\n<p>La suddivisione in due file .h e .m ha il solo scopo di separare formalmente la &#8220;<em>descrizione<\/em>&#8221; di una classe dalla sua implementazione. La &#8220;descrizione&#8221; di una classe in OOP si chiama &#8220;<strong>interfaccia<\/strong>&#8221; ed \u00e8 costituita dall&#8217;elenco dei metodi e, se ci sono, l&#8217;elenco delle variabili di istanza. Questo \u00e8 tutto quello che serve ad un ipotetico utilizzatore della nostra classe, il quale la potr\u00e0 utilizzare come una semplice <em>blackbox<\/em> che esegue quanto specificato nell&#8217;interfaccia, senza curarsi dell&#8217;<strong>implementazione<\/strong>. Nel nostro caso l&#8217;utilizzatore della nostra classe non avr\u00e0 accesso diretto alle variabili <em>numerator<\/em> e <em>denumerator<\/em> se non utilizzando gli appositi metodi <em>setNumerator<\/em> e <em>setDenumerator<\/em>. Questo ci ha dato la possibilit\u00e0 di inserire un controllo sul valore del denominatore che sarebbe stato pressocch\u00e8 impossibile altrimenti.<\/p>\n<p>Questo \u00e8 il primo pilastro della OOP, ovvero l&#8217;<strong>incapsulamento<\/strong><em>, l&#8217;arte del nascondere l&#8217;implementazione.<\/em> In realt\u00e0 la faccenda \u00e8 un p\u00f2 pi\u00f9 complicata di cos\u00ec, perch\u00e8 la presenza di opportuni modificatori (@public, @private , @protected etc) permettono di variare la visibilit\u00e0 delle variabili di istanza e dei metodi, ma al momento ci accontentiamo di sapere che fornire una corretta interfaccia alla classe e nascondere l&#8217;implementazione assicura versatilit\u00e0 e possibilit\u00e0 di riutizzo del codice.<\/p>\n<p>Dopo il nome della classe ed i due punti troviamo il nome della superclasse, in questo caso NSObject. Ma a che serve specificare una superclasse? Serve, banalmente, a sfruttare il lavoro gi\u00e0 svolto. Supponiamo di aver gi\u00e0 creato e testato la classe &#8220;persona&#8221; con tutti i suoi metodi quando ci commissionano un programma\u00a0 per gestire il personale di un ufficio, avremo probabilmente bisogno di aggiungere alcune propriet\u00e0 alla classe persona, per esempio &#8220;reparto&#8221; oppure &#8220;livello&#8221; etc. <\/p>\n<p>In questo caso entra in gioco l&#8217;<strong>ereditariet\u00e0<\/strong>, perch\u00e8 piuttosto che creare ex novo la classe <em>impiegato<\/em> potremo semplicemente specificare che la sua superclasse \u00e8 la classe <em>persona.<\/p>\n<p><\/em>Questo significa che <em>impiegato<\/em> eredita automaticamente da <em>persona<\/em> tutti i suoi metodi e tutte le variabili di istanza, senza scrivere una riga di codice! Supponendo per esempio che la classe persona abbia un metodo chiamato <em>getCodicePersonale<\/em> sar\u00e0 possibile invocarlo automaticamente anche su oggetti di tipo <em>impiegato.<\/em><br \/>\nVi siete mai chiesti come sia possibile invocare su qualsiasi oggetto i metodi <em>alloc, init, dealloc<\/em> anche se in realt\u00e0 non li abbiamo scritti? Semplice, perch\u00e8 sono definiti nella classe NSObject dalla quale tutte le altre discendono, quindi vengono automaticamente ereditati. <\/p>\n<p>E come mai su una <em>UILabel<\/em> posso invocare <em>initWithFrame<\/em> anche se nella class reference di UILabel non ce n&#8217;\u00e8 traccia? anche in questo caso la colpa \u00e8 dell&#8217;ereditariet\u00e0 perch\u00e8 se guardiamo bene vediamo che la classe UILabel \u00e8 sottoclasse di UIView la quale definisce il metodo <em>initWithFrame <\/em>che quindi \u00e8 automaticamente disponibile in tutte le sue sottoclassi.<\/p>\n<p>Un ulteriore flessibilit\u00e0 nell&#8217;eritariet\u00e0 \u00e8 data dalla possibilit\u00e0 di effettuare l&#8217;<strong>override<\/strong> dei metodi della superclasse. Questo che vuol dire? Vuol dire che se il metodo <em>getCodicePersonale<\/em> della classe persona restituisce, ad esempio, il codice fiscale, nella classe <em>impiegati<\/em> lo stesso metodo pu\u00f2 restituire il numero di matricola. Questo si ottiene semplicemente riscrivendo il metodo all&#8217;interno della sottoclasse.<\/p>\n<p>Il terzo pilastro della programmazione ad oggetti \u00e8 la possibilit\u00e0 di avere pi\u00f9 metodi con lo stesso nome che svolgono compiti diversi, questa che a prima vista sempre un&#8217;assurdit\u00e0 si chiama <strong>polimorfismo<\/strong>, e permette ad esempio di dichiarare due metodi con lo stesso nome ma differente tipo di parametri con questa sintassi:<\/p>\n<pre lang=\"objc\" escaped=\"true\">\r\n- (void) stampaSchedaCliente:(int)codCliente;\r\n- (void) stampaSchedaCliente:(NSStrng *)nomeCliente;\r\n<\/pre>\n<p>a seconda del tipo di parametro che verr\u00e0 passato al metodo sar\u00e0 invocata l&#8217;implementazione corrispondente.<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/supporto-applicazioni\/parole-vietate-di-ignazio-calo\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2264\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/02\/bannerIgnazioc.png\" alt=\"\" width=\"480\" height=\"100\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/02\/bannerIgnazioc.png 480w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/02\/bannerIgnazioc-300x62.png 300w\" sizes=\"auto, (max-width: 480px) 100vw, 480px\" \/><\/a><br \/>\n<\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Con l&#8217;articolo di oggi non intendo scrivere un trattato sulla teoria della programmazione ad oggetti, non ne&#8230;<\/p>\n","protected":false},"author":53,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[9],"tags":[46,5,18,4],"class_list":["post-1199","post","type-post","status-publish","format-standard","hentry","category-guide-teoriche","tag-developer-iphone","tag-objective-c","tag-oop","tag-programmazione"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/1199","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/users\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=1199"}],"version-history":[{"count":14,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/1199\/revisions"}],"predecessor-version":[{"id":3207,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/1199\/revisions\/3207"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=1199"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=1199"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=1199"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}