|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: Jun 2006
Messaggi: 117
|
[C#] metodi e campi protected
Credo che qualcosa non mi torni sulla teoria OOP in merito all'utilizzo della keyword protected...
Test banalissimo: Codice:
public class Edificio { public Edificio() { } protected void entra() { ... } } public class Villetta : Edificio { public Villetta() { this.entra(); <---- OK. VEDO IL METODO entra() } } public static void main() { Edificio e = new Edificio(); Villetta v = new Villetta(); e.entra() <---- NON VEDO IL METODO entra() v.entra() <---- NON VEDO IL METODO entra() } Perche' nella sotto-classe Villetta posso vedere e chiamare il metodo entra() che ha ereditato da Edificio, mentre dal main non posso accedere al metodo entra() attraverso le istanze sia di Villetta che di Edificio? |
![]() |
![]() |
![]() |
#2 |
Registered User
Iscritto dal: May 2009
Messaggi: 300
|
Semplicemente perchè sbagli! Guarda ora ti dico come funziona in C++ perchè in Java ho poca pratica, ma dovrebbe essere lo stesso. Hai tre possibili parole chiave:
1) private: quello che dichiari privato è visibile solo all'interno della classe e non viene ereditato dalle sottoclassi; 2) protected: quello che dichiari protetto è visibile solo all'interno della classe e viene ereditato dalle sottoclassi, quindi è visibile anche all'interno di esse; 3) public: quello che dichiari pubblico è visibile all'interno della classe, ma anche all'esterno, inoltre viene ereditato dalle sottoclassi ed è visibile in esse ed all'esterno di esse. In particolare in C++: nel caso in cui una sottoclasse ridefinisce un membro o una funzione protetta o pubblica, è possibile continuare a riferire la versione della superclasse attraverso l'operatore risolutore di visibilità "::". |
![]() |
![]() |
![]() |
#3 |
Registered User
Iscritto dal: May 2009
Messaggi: 300
|
Per fare quello che vuoi fare tu, devi scrivere public e non protected, come hai fatto per il costruttore!
|
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Ma se te lo dovessero chiedere ad un colloquio, la risposta giusta e': Seppur viene ereditato nelle sottoclassi, esso non e' da esse visibile. Un oggetto di un tipo derivato ha tutte le proprieta', campi e i metodi dei tipi padre, anche quelli privati. Solo che i privati non li potra' vedere direttamente. Ma indirettamente si' pero'. Pensa a quando si richiama un metodo protected o public derivato dalla classe padre, il quale a sua volta fa uso di un metodo o un campo privato della stessa classe padre. Se il metodo o campo privato in questione non esistesse, ovvero se non fosse ereditato seppur invisibile alla classe figlia, si avrebbe un'anomalia.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#5 |
Member
Iscritto dal: Jun 2006
Messaggi: 117
|
Allora... devo ragionarci un po' su per capire bene perche' mi e' sempre sembrato banale e invece...
Quello che sicuramente mi sembra piu' strano e' che la stessa classe Edificio non puo' chiamare il metodo protected entra() attraverso un'istanza di se stesso... eppure il metodo e' praticamente il suo... non e' stato ereditato da nessuna classe ancora superiore gerarchicamente! Ultima modifica di mcaisco : 28-05-2009 alle 17:44. |
![]() |
![]() |
![]() |
#6 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Quel pezzo di main non e' dentro la classe stessa, quindi ne le protected ne tantomento le private possono essere richiamate. E' il concetto dell'incapsulamento dell OO. http://it.wikipedia.org/wiki/Incapsu..._(informatica)
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#7 |
Member
Iscritto dal: Jun 2006
Messaggi: 117
|
Mmm. Beh io fino ad ora il concetto di incapsulamento l'avevo sempre pensato cosi:
"un oggetto istanza di una classe A, puo' accedere ai metodi e ai campi di un oggetto di una classe B solo se questi sono dichiarati public, o nel caso in cui questi siano dichiarati protected e la classe A sia derivata dalla classe B" Invece a questo punto il concetto come lo pensavo io e' valido solo per campi e metodi public. Mentre con protected o private le regole rispettive si applicano ma all'interno della classe, e non centrano piu' nulla le istanze. ![]() |
![]() |
![]() |
![]() |
#8 |
Registered User
Iscritto dal: May 2009
Messaggi: 300
|
X gugoXX: lo so era una spiegazione approssimativa. L'utente che ha posto la domanda è all'inizio quindi volevo risparmiargli le complicazioni del caso. Certamente al professore di Fondamenti di Informatica II non ho risposto così
![]() ![]() ![]() ![]() ![]() X mcaisco: Ti sfugge il concetto di classe! Tutto qua. Se conosci quello capisci anche cosa è l'incapsulamento anche detto "information hiding". Adesso ti spiego meglio, perchè potrebbe essere utile a molti altri alle prime armi con questi concetti (come diceva il mio Prof. se uno di voi fa una domanda, ce ne sono almeno altri 10 che hanno lo stesso dubbio). Partiamo dalla base: considera una variabile di tipo "int", questa è un "tipo di dato". Una variabile "double" è un "tipo di dato". Anche la classe è un tipo di dato. In quanto tale è caratterizzata da 2 elementi: 1) Una rappresentazione interna del tipo di dato, ovvero il modo in cui il tipo viene rappresentato nella memoria. A livello astratto ciò si traduce in una cosa che chiamiamo "valore" che possiamo assegnare al tipo. In un certo momento dell'esecuzione i valori assegnati ad una istanza del tipo di dato ne costituiscono lo "stato". 2) Operazioni concrete intese come istruzioni macchina che possono lavorare sulle rappresentazioni dei dati. A livello astratto parliamo di "operazioni di alto livello". Queste permettono di far variare i "valori" dell'istanza del tipo di dato e quindi di farne evolvere lo "stato". Queste operazioni costituiscono l'unico punto di accesso alla rappresentazione interna del tipo, il quale quindi non può essere modificato altrimenti. L'information hiding, significa proprio nascondere i valori all'interno di una membrana protettiva che può essere oltrepassata solo dalle operazioni che il tipo di dato definisce. Perciò se vuoi modificare il tipo int puoi usare =, +, -, *, ecc... ma oltre a questi operatori non hai altro modo per metterci su le mani. Una classe realizza il medesimo comportamento attraverso: 1) Campi membro 2) Funzioni membro In una prima analisi possiamo pensare quindi ai campi membro come un insieme di tipi primitivi e non che possono essere acceduti solo dalle funzioni membro della classe. Quindi all'esterno della classe tu vedi solo le funzioni membro, non gli int, i double, ecc... (campi membro) che costituiscono i membri interni alla classe. Il discorso si complica quando generalizzi i concetti. In realtà la distinzione non è tra campi membro e funzioni membro, ma tra membri privati e membri pubblici. Un membro privato è quello che sta all'interno della membrana. Un membro pubblico è al confine della membrana e può essere visto all'esterno di essa, ma è l'unico punto di accesso per operare sulla parte privata che sta all'interno. Per membro quindi ci può essere tanto un campo (caratterizzato a sua volta in un tipo di dato che può non essere primitivo) tanto una funzione. Pertanto abbiamo già una certa tassonomia: 1) Campi privati 2) Campi pubblici 3) Funzioni private 4) Funzioni pubbliche Chi usa la classe può riferire i campi e le funzioni pubbliche e basta. Mentre le funzioni private possono essere chiamate solo dalle funzioni pubbliche. Se non consideri la derivazione, definire una funzione protected o private è la stessa cosa! Di fatto si può dire che è indifferente l'uso di un classificatore o dell'altro. Per chiarirti le idee pensa di usare sempre "private" e non "protected" (e non preoccuparti del meccanismo della derivazione). In questo caso la funzione membro entra() non potrebbe essere invocata dall'esterno della classe perchè è una funzione privata!!! Allora xkè discriminare tra protected e private??? Qui entra in gioco la derivazione... La derivazione è il gioco delle scatole cinesi: se tu derivi una classe non hai fatto altro che prendere una scatola più grande e metterci dentro la superclasse cioè la scatola più piccola! A questo punto mi devo chiedere la seguente domanda: Chi sta all'interno della scatola grande (la sottoclasse) cosa vede della scatola piccola (della superclasse)??? Vede sicuramente gli unici punti di accesso pubblici e quindi i membri pubblici. Pertanto ciò che è pubblico nella superclasse è pubblico nella sottoclasse Ma i membri privati? No quelli non sono visibili all'esterno della superclasse e quindi non saranno visibili nemmeno all'esterno della sottoclasse! E la via di mezzo qual è??? Il membro protetto. Il membro protetto non è visibile all'esterno della superclasse (perchè è come se fosse privato), non è visibile all'esterno della sottoclasse (perchè continua a comportarsi come se fosse privato). Differisce però dai membri privati, per il fatto che una qualsiasi funzione membro della sottoclasse (qualunque sia il suo genere) riesce a vederlo! Cosa che non succedeva con il membro privato! Ora preparo alcuni esempi chiarificatori! |
![]() |
![]() |
![]() |
#9 |
Registered User
Iscritto dal: May 2009
Messaggi: 300
|
Non guardate la sintassi, ma solo la semantica del seguente codice:
Codice:
class Superclasse { private campi_membro_privati_superclasse; protected campi_membro_protetti_superclasse; public campi_membro_pubblici_superclasse; private void funzioni_membro_private_superclasse(); protected void funzioni_membro_protette_superclasse(); public void funzioni_membro_pubbliche_superclasse(); } class Sottoclasse : Superclasse { private campi_membro_privati_sottoclasse; protected campi_membro_protetti_sottoclasse; public campi_membro_pubblici_sottoclasse; private void funzioni_membro_private_sottoclasse(); protected void funzioni_membro_protette_sottoclasse(); public void funzioni_membro_pubbliche_sottoclasse(); } Codice:
Superclasse super; Sottoclasse sotto; super.campi_membro_privati_superclasse; //errore super.campi_membro_protetti_superclasse; //errore super.campi_membro_pubblici_superclasse; // visibile super.funzioni_membro_private_superclasse(); //errore super.funzioni_membro_protette_superclasse(); //errore super.funzioni_membro_pubbliche_superclasse(); //visibile sotto.campi_membro_privati_superclasse; //errore sotto.campi_membro_protetti_superclasse; //errore sotto.campi_membro_pubblici_superclasse; // visibile sotto.campi_membro_privati_sottoclasse; //errore sotto.campi_membro_protetti_sottoclasse; //errore sotto.campi_membro_pubblici_sottoclasse; // visibile sotto.funzioni_membro_private_superclasse(); //errore sotto.funzioni_membro_protette_superclasse(); //errore sotto.funzioni_membro_pubbliche_superclasse(); //visibile sotto.funzioni_membro_private_sottoclasse(); //errore sotto.funzioni_membro_protette_sottoclasse(); //errore sotto.funzioni_membro_pubbliche_sottoclasse(); //visibile Codice:
Superclasse::campi_membro_privati_superclasse; //errore Superclasse::campi_membro_protetti_superclasse; //visibile Superclasse::campi_membro_pubblici_superclasse; // visibile Superclasse::funzioni_membro_private_superclasse(); //errore Superclasse::funzioni_membro_protette_superclasse(); //visibile Superclasse::funzioni_membro_pubbliche_superclasse(); //visibile Sottoclasse::campi_membro_privati_sottoclasse; //visibile Sottoclasse::campi_membro_protetti_sottoclasse; //visibile Sottoclasse::campi_membro_pubblici_sottoclasse; // visibile Sottoclasse::funzioni_membro_private_sottoclasse(); //visibile Sottoclasse::funzioni_membro_protette_sottoclasse(); //visibile Sottoclasse::funzioni_membro_pubbliche_sottoclasse(); //visibile Ultima modifica di Ikon O'Cluster : 28-05-2009 alle 18:46. |
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
ma non è che semplicemente volevi definirlo come internal o internal protected?
![]() quando è definito come internal allora tutte le classi dello stesso progetto possono accedervi, con internal protected, vi possono accedere tutte le sottoclassi e tutte le classi dello stesso progetto se non erro....
__________________
![]() |
![]() |
![]() |
![]() |
#11 |
Registered User
Iscritto dal: May 2009
Messaggi: 300
|
internal???
|
![]() |
![]() |
![]() |
#12 |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
![]() si... non stavamo parlando di C#? ![]() mi pare che internal è nel C# e nel java c'è package come visibilità, sempre se non ricordo male....
__________________
![]() |
![]() |
![]() |
![]() |
#13 |
Registered User
Iscritto dal: May 2009
Messaggi: 300
|
No chiedevo per sapere che roba era
![]() |
![]() |
![]() |
![]() |
#14 |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
è una parola chiave per definire la visibilità nel c# che dovrebbe essere equivalente alla visibilità di tipo package in java (che è quella di default) se non mi sto dimenticando niente.
![]()
__________________
![]() |
![]() |
![]() |
![]() |
#15 |
Member
Iscritto dal: Jun 2006
Messaggi: 117
|
Grazie a tutti per le correzioni.
In realta' non sono alle prime armi ma evidentemente avevo sempre applicato l'incapsulamento/ereditarieta' in maniera corretta senza aver compreso che la visibilita' e' a livello di classe e non anche di istanza... io pensavo che valesse per entrambi. Evidentemente fino ad ora l'avevo applicata bene senza incappare mai in errori... fino a ieri! Beh meglio cosi'. Ora non ci casco piu'. Comunque la domanda era inizialmente inerente a C# perche' pensavo che quel comportamento fosse di C#. Invece a questo punto e' proprio il comportamento standard del modificatore protected in OOP. Credo che il modificatore "protected internal" di C# imponga la visibilita' a livello di assembly .net, cioe' tutte le classi appartenenti ad uno stesso assembly .net vedono quei campi o quei metodi internal protected. Diciamo che e' un livello di visibilita' superiore al package di java, il quale invece in C# e' tradotto con il concetto di namespace. Infatti in uno stesso assembly .net ci possono essere piu' namespace (package). |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 09:47.