Documente Academic
Documente Profesional
Documente Cultură
1. Obiective
Obiectivele capitolului 7 sunt urmtoarele: Implementarea unui program dup ablonul de proiectare Metoda Fabric (engl. Factory Method); Precizarea unor noiuni privind motenirea i polimorfismul (clase abstracte, interfee, membri virtuali), utilizate n majoritatea abloanelor de proiectare.
O alt diagram n care avem doi creatori i dou produse este prezentat n figura 7.2.
Metoda Fabric se folosete n general atunci cnd o clas nu poate ti sau nu dorete s specifice din ce clas va fi creat un obiect i n consecin las clasele derivate s specifice clasa acestuia.
3. Exemplu de implementare
Codul C# corespunztor diagramei UML anterioare este prezentat mai jos. Clasele Produs
abstract class Product { } class ConcreteProductA : Product { } class ConcreteProductB : Product { }
152
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
Clasele Creator
abstract class Creator { // Metode abstract public Product FactoryMethod(); }
class ConcreteCreatorA : Creator { // Metode override public Product FactoryMethod() { return new ConcreteProductA(); } } class ConcreteCreatorB : Creator { // Metode override public Product FactoryMethod() { return new ConcreteProductB(); } }
Clientul
class Client { public static void Main( string[] args ) { // FactoryMethod returneaz ProductA Creator c = new ConcreteCreatorA(); Product p = c.FactoryMethod(); Console.WriteLine("A fost creat {0}", p ); // FactoryMethod returneaz ProductB c = new ConcreteCreatorB(); p = c.FactoryMethod(); Console.WriteLine("A fost creat {0}", p ); } }
153
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
4. Motenirea i polimorfismul
4.1. Polimorfismul
Cu ajutorul motenirii, o clas poate fi folosit ca i cum ar reprezenta mai multe tipuri. Ea poate fi folosit ca propriul su tip, ca un tip de clas de baz, sau un tip de interfa pe care o implementeaz. Acest comportament este numit polimorfism. n C#, orice tip este polimorfic. Un tip poate fi folosit aa cum este sau ca o instan de object, pentru c orice tip consider automat tipul object ca tip de baz. Polimorfismul este important nu numai pentru clasele derivate, ci i pentru clasele de baz. Cnd se folosete o clas de baz, se poate folosi de fapt orice clas derivat. Proiectanii unei clase de baz pot anticipa aspectele claselor care se vor modifica prin derivare. De exemplu, o clas de baz pentru maini poate conine membri care se modific dac maina este o dubi sau o main decapotabil. O clas de baz poate marca acei membri ca virtuali, dnd posibilitatea claselor derivate care reprezint maina decapotabil i dubia s suprascrie comportamentul respectiv. Cnd o clas derivat motenete o clas de baz, ea primete toate metodele, cmpurile, proprietile i evenimentele clasei de baz. Pentru a modifica datele i metodele unei clase de baz exist dou posibiliti: se poate nlocui clasa de baz cu una derivat sau se poate suprascrie un membru virtual din clasa de baz.
O clas abstract nu poate fi instaniat. Scopul su este s ofere o definiie comun pentru mai multe clase derivate. De exemplu, o bibliotec de clase poate defini o clas abstract care este folosit ca parametru n mai
154
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
multe funcii din bibliotec i necesit ca dezvoltatorii care o folosesc s asigure o implementare proprie prin crearea unei clase derivate. Clasele abstracte pot de asemenea s defineasc metode abstracte, prin adugarea cuvntului cheie abstract n faa tipului returnat de metod. De exemplu:
public abstract class A { public abstract void Method(int i); }
Metodele abstracte nu au implementare i deci definiia metodei este urmat de ; n locul unui bloc normal de cod. Clasele derivate neabstracte trebuie s implementeze toate metodele abstracte.
4.3. Interfee
Interfeele sunt definite cu ajutorul cuvntului cheie interface. De exemplu:
interface IComparable { int CompareTo(object obj); }
Interfeele descriu un grup de funcionaliti asemntoare care pot s aparin oricrei clase sau structuri. Interfeele pot conine metode, proprieti, evenimente sau indeci, ns nu pot conine cmpuri. Membrii unei interfee sunt implicit publici. Clasele i structurile pot moteni interfee ntr-un mod asemntor claselor care motenesc clase sau structuri, cu dou excepii:
O clas sau structur poate moteni mai multe interfee; Cnd o clas sau structur motenete o interfa, motenete doar numele metodelor i semnturile acestora, deoarece interfeele nu conin implementri.
n exemplul urmtor, clasa Minivan este derivat din clasa Car i implementeaz interfaa IComparable.
155
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
Florin Leon Aplicaii de ingineria programrii n C# public class Minivan : Car, IComparable { public int CompareTo(object obj) { // implementarea metodei CompareTo return 0; // dac obiectele sunt egale } }
Pentru a implementa un membru al unei interfee, membrul respectiv trebuie s fie public, nestatic i s aib acelai nume i semntur cu membrul interfeei. Interfeele pot moteni alte interfee. Este posibil ca o clas s moteneasc o interfa de mai multe ori, printr-o clas sau interfa motenit. n acest caz, clasa poate implementa interfaa doar o dat. O interfa are urmtoarele caracteristici:
Este similar unei clase de baz abstracte: orice tip neabstract care motenete o interfa trebuie s i implementeze toi membrii; O interfa nu poate fi instaniat direct; Interfeele pot conine metode, proprieti, evenimente i indeci; Interfeele nu conin implementri ale metodelor; Clasele i structurile pot moteni mai multe interfee; O interfa poate ea nsi s moteneasc mai multe interfee.
156
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
Capitolul 7. ablonul de proiectare Metoda Fabric public virtual int Property { get { ... } } } public class DerivedClass : BaseClass { public override void Method() { ... } public override int Property { get { ... } } }
Cmpurile nu pot fi virtuale, doar metodele, proprietile i indecii. Cnd o clas derivat suprascrie un membru virtual, acel membru este apelat chiar i atunci cnd o instan a acelei clase este accesat ca o instan a clasei de baz. De exemplu:
DerivedClass B = new DerivedClass(); B.Method (); // Apeleaz metoda nou BaseClass A = (BaseClass)B; A.Method (); // Apeleaz tot metoda nou
Un membru virtual rmne astfel n toat ierarhia de clase, indiferent de numrul de niveluri dintre clasa de baz i cea curent. Dac n clasa A este declarat un membru virtual i clasa B este derivat din clasa A iar clasa C este derivat din clasa B, atunci clasa C motenete membrul virtual i poate s l suprascrie, chiar dac n clasa B el a fost deja suprascris. De exemplu:
public class A { public virtual void Method() { ... } } 157
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
Florin Leon Aplicaii de ingineria programrii n C# public class B : A { public override void Method() { ... } } public class C : B { public override void Method() { ... } }
O clas sigilat nu poate fi folosit drept clas de baz. Din aceast cauz, ea nu poate fi nici abstract. Clasele sigilate sunt folosite, n principiu, pentru a preveni derivarea. Neputnd fi folosite ca i clase de baz, unele optimizri n timp real pot face apelul membrilor acestora mai rapid. Un membru, o metod, o proprietate sau un eveniment al unei clase derivate care suprascrie un membru virtual al clasei de baz poate declara acel membru ca sigilat. Astfel se elimin aspectul virtual al membrului pentru orice clas viitoare derivat. De exemplu:
158
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
Capitolul 7. ablonul de proiectare Metoda Fabric public class B { public virtual void Method() { ... } } public class C : B { public sealed override void Method() { ... } }
n exemplul anterior, metoda Method nu mai este virtual pentru nicio clas derivat din C. Dar este nc virtual pentru instanele clasei C.
159
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
Florin Leon Aplicaii de ingineria programrii n C# public class DerivedClass : BaseClass { public new void Method() { ... } public new int Property { get { ... } } }
Cnd se folosete cuvntul cheie new, noul membru este apelat n locul celui vechi, nlocuit. Membrii respectivi ai clasei de baz sunt numii membri ascuni. Ei mai pot fi apelai doar dac o instan a clasei derivate este convertit prin cast la o instan a clasei de baz. De exemplu:
DerivedClass B = new DerivedClass(); B.Method (); // Apeleaz metoda nou BaseClass A = (BaseClass)B; A.Method (); // Apeleaz metoda veche
160
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
Capitolul 7. ablonul de proiectare Metoda Fabric public class B : A { public override void Method() { ... } } public class C : B { public override void Method() { // apeleaz Method din B pentru a utiliza comportamentul lui B base.Method(); // comportamentul specific lui C urmeaz n continuare ... } }
Se recomand ca un membru virtual s utilizeze cuvntul cheie base pentru a apela implementarea membrului din clasa de baz n implementarea proprie. Prin aceasta este lsat clasa derivat s se axeze pe implementarea propriilor funcionaliti. Dac nu este apelat implementarea din clasa de baz, atunci clasa derivat va trebui s se ocupe de implementarea unor funcionaliti similare cu acelea ale clasei de baz. Cuvntul cheie base este folosit:
Pentru a apela o metod din clasa de baz care a fost suprascris de o alt metod; Pentru a specifica clasa de baz al crei constructor s fie apelat la instanierea clasei derivate.
Din metodele statice nu este permis accesul la clasa de baz prin cuvntul cheie base.
5. Aplicaii
5.1. Realizai o aplicaie care deschide i afieaz fiiere text i grafice (figura 7.3). Testul se va efectua dup extensia fiierului (txt, rtf, bmp, jpg). Se va utiliza ablonul de proiectare Metoda fabric.
161
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
Aplicaia deschide fiiere index cu extensiile txd, pentru fiiere text, respectiv grd, pentru fiiere grafice. Aceste fiiere index conin cile ctre mai multe fiiere cu extensiile txt sau rtf, respectiv bmp sau jpg. Un exemplu privind structura de directoare i fiiere, precum i coninutul fiierelor index este prezentat n figura 7.4. Diagrama de clase este prezentat n figura 7.5.
Indicaii. Pentru citirea fiierelor text se poate utiliza clasa StreamReader din System.IO. Pentru fiierele text i rtf se poate utiliza clasa RichTextBox din System.Windows.Forms cu metoda LoadFile. Pentru
163
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
fiierele grafice se poate utiliza clasa Bitmap unde numele fiierului este primit n constructor sau proprietatea ImageLocation din clasa PictureBox. Pentru deschiderea unui fiier se utilizeaz un control OpenFileDialog. Pentru a se deschide doar tipurile de fiiere cu extensiile txd sau grd, se seteaz proprietatea Filter cu valoarea "Text documents (*.txd)|*.txd|Graphic documents (*.grd)|*.grd". n evenimentul corespunztor butonului Open, se poate prelucra un fiier doar dac utilizatorul a ales un fiier i a dat OK n fereastra de deschidere de fiiere.
if (openFileDialog.ShowDialog() != DialogResult.OK) return;
Apoi se testeaz valoarea proprietii FilterIndex din obiectul openFileDialog, care indic tipul de fiier deschis (index text sau index grafic). Indexul pleac de la 1, nu de la 0. n continuare, se instaniaz un obiect TextDocument sau un GraphicDocument. Afiarea paginilor n obiectul tabControl se poate face n modul urmtor:
Document doc; ... // crearea obiectului document (creatorul concret) tabControl.Controls.Clear(); foreach (Page p in doc.Pages) { TabPage tp = new TabPage(p.Name); p.Content.Dock = DockStyle.Fill; tp.Controls.Add(p.Content); tabControl.TabPages.Add(tp); }
Secvena de cod de mai sus se recomand a fi inclus ntr-un bloc de tratare a excepiilor, deoarece pot aprea probleme referitoare la deschiderea unui fiier care s nu conin ci valide sau fiierele indicate de aceste ci s nu aib coninutul ateptat. n produsele concrete se creeaz controalele corespunztoare iar numele paginilor afiate n tabControl se determin din numele fiierului ncrcat:
_name = Path.GetFileNameWithoutExtension(fileName);
164
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com
n constructorul creatorului abstract (Document) se citete fiierul index linie cu linie i se creeaz paginile corespunztoare:
StreamReader sr = new StreamReader(indexFileName); string line; while ((line = sr.ReadLine()) != null) { if (line != string.Empty) _pages.Add(CreatePage(line)); } sr.Close();
ns deoarece metoda CreatePage este abstract, deciziile privind tipul efectiv al paginii vor fi luate de clasele derivate din Document. 5.2. Tem pentru acas. Adugai n proiect un nou tip de pagin care s afieze un document Microsoft Word i/sau un document PDF.
165
Florin Leon (2012). Aplicatii de ingineria programarii in C#, Tehnopress, Iasi, ISBN 978-973-702-909-6 http://florinleon.byethost24.com