Programmering i C# 3. Klasser
3.1 Inkapsling och datagömning Inkapsling innebär paketering av funktioner och det data de ska hantera Klasser och structer Datagömning innebär att access till data kan kontrolleras med hjälp av synlighetsmodifierare Fem nivåer: public, private, protected, internal, internal protected Programmering i C# - Kapitel 3
3.2 Fält (fields) Medlemmar kan vara funktioner, variabler eller typer Åtskilliga varianter i C#: Fält är medlemsvariabler Klassreferenser, interfacereferenser, structer Görs aldrig public i klasser, men ofta i structer Initieras automatiskt till noll (eller motsv.) Programmering i C# - Kapitel 3
Initiering av fält class Trivial // klassdeklarationen { int val = 100; // default synlighet: private string str = ”Etthundra”; double[] vec = new double[100]; MyClass obj1 = new MyClass(); YourClass obj2 = null; // endast för tydlighet // blir ändå null public int GetVal() { return val; } } Programmering i C# - Kapitel 3
Skrivskyddade fält Två sätt skrivskydda fält: Initiera med literal – const Endast typer som kan skrivas literalt Tilldela en gång – readonly I klassdeklaration eller konstruktor Alla typer, även referenser Programmering i C# - Kapitel 3
Skrivskyddade fält, exempel class Trivial { const int val = 100; const string str = ”Ständigt innehåll”; readonly SomeClass obj = new SomeClass(); public int GetVal() { return val; // alltid 100 } } Programmering i C# - Kapitel 3
Statiska fält Instansmedlemmar ingår i objekt Statiska medlemmar finns i ett enda gemensamt exemplar Refereras endast med klassnamn Konstant medlem blir också statisk! Trivial obj = new Trivial(); ... obj.val; // Fel, val är const och därmed static ... Trivial.val; // Rätt! Programmering i C# - Kapitel 3
3.3 Konstruktorer Konstruktor är en metod med samma namn som klassen Skapar objekt av klassen Kan överlagras med olika parameterlistor Ingen deklarerad returtyp Klass utan konstruktor får en parameterlös defaultkonstruktor automatiskt genererad Trivial obj = new Trivial(); // defaultkonstruktorn Programmering i C# - Kapitel 3
Egna konstruktorer class Rational { int numerator, denominator; public Rational(): this(0, 1) {} public Rational(int n): this(n, 1) {} public Rational(double val): this((int)(val * 1000), 1000) {} public Rational(int n, int d) { if (d == 0) d = 1; numerator = n; denominator = d; } } Programmering i C# - Kapitel 3
3.4 Metoder (methods) Definieras alltid med returtyp, namn och parameterlista, samt kropp Parameterlistan kan vara tom Flera metoder med samma namn men olika parameterlista tillåts (överlagring) Structparameter ger värdeanrop Referensparameter ger referensanrop Klassobjekt alltid referens Programmering i C# - Kapitel 3
Parameteröverföring static void F(int x, int[] vec) { x = 100; vec[0] = 100; } static void Main() { int i = 0; int[] iv = new int[3]; // alla är 0 F(i, iv); Console.WriteLine(”{0}, {1}”, i, iv[0]); // ”0, 100” Programmering i C# - Kapitel 3
Referensanrop med struct Referensanrop med struct fås med modifierarna ref eller out Anges både i definition och i anrop Liten skillnad: out kan vara oinitierad static void F(ref int x, int[] vec) { … // gör något med x } static void Main() { … F(ref i, iv); } // i kan ändras av anropet Programmering i C# - Kapitel 3
Statiska metoder Även metoder kan vara static Anropas via klassnamn Kan endast se andra statiska medlemmar Även const är statiska! Instansmetoder har osynlig parameter this Refererens till det aktuella objektet Statiska metoder har ingen this Programmering i C# - Kapitel 3
3.5 Egenskaper (properties) Ser ut som fält men är metoder Kan dölja ett fält som annars kunde vara public Gör aldrig fält public! Kan ha valfri logik, som en metod Kan ha set och/eller get Bara get ger skrivskydd Programmering i C# - Kapitel 3
Egenskaper exempel public string MyProp { get { return myField; } set { myField = value; } } obj.MyProp = ”Ny sträng”; Programmering i C# - Kapitel 3
Statisk egenskap som konstruktor Vanlig design i många klasser: Statiska egenskaper som returnerar typiska objekt Anropar någon konstruktor public static Color Red { get { return new Color(255, 0, 0); } } Color obj = Color.Red; Programmering i C# - Kapitel 3
3.6 Operatorer Alla operatorer är metoder i respektive klass eller struct Valfritt förse egna typer med operatorer Operatorer är statiska metoder där minst en parameter (operand) är av aktuell typ En operand: en parameter Två operander: två parametrar Programmering i C# - Kapitel 3
Operatorer forts. Endast operatorer från standarduppsättning public static X operator+(X left, X right) { … } Endast operatorer från standarduppsättning Nya kan inte uppfinnas Prioritet och associativitet enligt reglerna Unär/binär såsom operatorn Tilldelningsoperatorn kan inte överlagras Programmering i C# - Kapitel 3
Operator ++ och -- Ensam om egenheten att vara prefix eller postfix Kan inte överlagras specifikt för ++x/x++ Måste returnera objekt av aktuell typ Får ej ändra aktuellt objekts tillstånd Programmering i C# - Kapitel 3
Indexoperatorn Vanligt behov är att kunna överlagra specifikt för lvalue/rvalue Problematiskt i exempelvis C++ C# har valt annan syntax (”indexerare”) public X this[int i] { get { … } set { … } } Programmering i C# - Kapitel 3
Specialfall Kombinationerna överlagras inte explicit +=, *=, <<=, etc. Operatorn anropas, därefter tilldelning && och || överlagras med särskild syntax Mycket litet behov Ytterligare några kan ej överlagras: is, as, typeof, new, . och ?: Programmering i C# - Kapitel 3
3.7 Typomvandlare Implicit och explicit typomvandling är också egentligen metoder i klasser/structer Undantaget upcast/downcast Egna typer kan göras kompatibla med andra genom typomvandlare Syntax som liknar operatorer Programmering i C# - Kapitel 3
Typomvandlare exempel class Rational { private int numerator, denominator; ... public static implicit operator double(Rational obj) { return (double)obj.numerator/obj.denominator; } } Typomvandlaren måste markeras implicit eller explicit Programmering i C# - Kapitel 3
Typomvandlare forts. Omvandling till egen typ också relevant Exempelvis double till Rational Blir parallell till konstruktor Anropar typiskt motsvarande enparameterskonstruktor Programmering i C# - Kapitel 3
3.8 Destruktor Skräpsamlaren raderar objekt vid odefinierad tidpunkt Objekt från klasser med destruktor hanteras i särskild kö Få klasser har behov av destruktor – i de fallen måste den kunna anropas explicit Men explicit konstruktoranrop finns inte! Programmering i C# - Kapitel 3
Dispose-mönstret Resursallokerande klasser ska ha destruktor och implementera IDisposable.Dispose Anrop till Dispose bör eliminera skräpsamlarens anrop till destruktor Efter anrop till Dispose bör objektet vara oanvändbart Dispose ska klara upprepade anrop Destruktor och Dispose ska inte dubblera varann Programmering i C# - Kapitel 3
Dispose-mönstret forts. class X : IDisposable { private bool disposed = false; ~X() { Dispose(false); } public void Dispose() { Dispose(true); } private void Dispose(bool disposing) { if (Disposed) return; // API-anrop som släpper resurser if (disposing) { disposed = true; GC.SuppressFinalize(this); } } Programmering i C# - Kapitel 3