4. Arv och dynamisk bindning Programmering i C# 4. Arv och dynamisk bindning
Arv Härledd klass ska representera något som är en sorts av det basklassen representerar Dimension som inte finns i funktionsorientering Ändrat beteende genom att lägga till ny kod – inte ändra i befintlig Arbetssätt som inte finns i funktionsorientering Härledd klass kan omdefiniera och utöka Endast en basklass kan förekomma Programmering i C# - Kapitel 4
Basklass class Shape { int x, y; // position public void Move(int x, int y) { this.x += x; this.y += y; } public double Area() { return 0.0; } } Programmering i C# - Kapitel 4
Härledd klass class Circle : Shape { int radius; public Circle(int radius) { this.radius = radius; } public new double Area() { return System.Math.PI * radius * radius; } public double Circumference() { return System.Math.PI * 2 * radius; } } Programmering i C# - Kapitel 4
Klientkod Shape shp = new Shape(); Console.WriteLine(shp.Area()); // alltid 0.0 Circle cle = new Circle(10); Console.WriteLine(cle.Area()); // 314.15... Härledd klass metoder och konstruktor kan ej nå koordinaterna! Är private i basklassen Programmering i C# - Kapitel 4
Synlighet public – synlig i egna metoder, i härledda klassers metoder och via objekt private – synlig endast i egna metoder protected – synlig i egna och härledda klassers metoder internal – som public, men endast mot klasser i samma assembly internal protected – kombination Programmering i C# - Kapitel 4
4.1 Arv kontra aggregering Arv ska endast användas i solklara fall Kom ihåg: en sorts! Vid tvekan använd aggregering Befintliga klassens logik återanvänds genom att ett objekt utgör medlem Poängen med arv är omdefinitioner och dynamisk bindning Programmering i C# - Kapitel 4
4.2 Konstruktorer och destruktor Allt ärvs – utom konstruktorer Utan konstruktoranrop skapas basklassdelen med sin klass defaultkonstruktor Basklasskonstruktor kan anropas från härledd klass konstruktor Gör den uppsättning konstruktorer som är relevant i härledda klassen! Programmering i C# - Kapitel 4
Konstruktorer exempel class Shape { int x, y; // position public Shape(int x, int y) // enda konstruktorn { this.x = x; this.y = y; } … Programmering i C# - Kapitel 4
Konstruktorer exempel forts. class Circle : Shape { int radius; public Circle(int x, int y, int radius): base(x, y) { this.radius = radius; } public Circle(int radius): base(0, 0) { this.radius = radius; } … Programmering i C# - Kapitel 4
Destruktorer Destruktor anropas automatiskt om sådan finns i aktuell klass eller någon basklass Basklassens destruktor först Kan inte anropas explicit Dispose i basklass bör anropas från härledd klass’ Dispose, om den finns Programmering i C# - Kapitel 4
4.3 Typomvandling Implicit uppåt – riskabel neråt Basklassreferens kan ha härlett objekt Aldrig tvärtom Shape shp = new Shape(100, 100); shp.Move(5, 5); // Shape-objektet flyttas shp = new Circle(100, 100, 50); shp.Move(5, 5); // Circle-objektet flyttas Programmering i C# - Kapitel 4
Två problem Om basklassreferens refererar till objekt av härledd klass, och: (1) anropad metod enbart finns i härledda klassen? (2) anropad metod är omdefinierad i härledda klassen? Programmering i C# - Kapitel 4
Downcast (1) Referensen måste typomvandlas till objektets typ Explicit typomvandling genererar undantag Använd is eller as if (shp is Circle) ((Circle)shp).Circumference(); // eller: Circle cle = shp as Circle; if (cle != null) cle.Circumference(); Programmering i C# - Kapitel 4
Virtuella metoder (2) Referensens typ avgör vilken klass’ metod som anropas Statisk bindning Oftast inte önskvärt – objektets typ bör avgöra val av metod Dynamisk bindning Metoden görs virtuell Programmering i C# - Kapitel 4
Virtuell metod, exempel class Shape { ... public double Area() { return 0.0: } } class Circle : Shape { ... public new double Area() { return System.Math.PI * radius * radius; } Programmering i C# - Kapitel 4
4.5 Abstrakta basklasser Om metoder ska kunna anropas måste de finnas i den basklass som är referensens typ Kan ofta inte implementeras i basklass Exempelvis Shape.Area() Lösning: gör metoden abstract Klassen blir då också abstrakt – objekt kan inte skapas Programmering i C# - Kapitel 4
Abstrakt klass forts. Abstrakt metod blir också virtuell abstract class Shape { ... public abstract double Area(); // override i härledd } Abstrakt metod blir också virtuell Även egenskaper kan göras abstrakta/virtuella Härledd klass som inte implementerar alla abstrakta basklassmetoder blir abstrakt Programmering i C# - Kapitel 4
4.6 Interface Ofta bra design samla enbart abstrakta metoder i egen klass Ger standardiserade interface Särskild syntax: interface Tredje kategorin datatyper av tre Får endast innehålla metoder, egenskaper, indexerare och notifierare Alla är alltid public Programmering i C# - Kapitel 4
Interface exempel interface IShape { void Move(int x, int y); double Area(); int SizeX { get; } int SizeY { get; } ... } Medlemmarna är inte virtuella och kan inte markeras virtual! Programmering i C# - Kapitel 4
Interface forts. Klass kan implementera flera interface Implementera == ärva Samtliga metoder måste implementeras Samtliga måste vara public, eller deklareras med interfacenamnet Blir då synliga endast via interfacereferens Programmering i C# - Kapitel 4
Dynamisk bindning från interface Metoder i interface är inte virtuella Klass som ärver klass som implementerar ett interface får inte dynamisk bindning Två lösningar: Återimplementera interfacet Mycket excentrisk språkmekanism Göra implementationerna virtual Programmering i C# - Kapitel 4
Återimplementera interfacet interface IA { void MA(); } class A : IA { public void MA() { ... } class B : A, IA // upprepad explicit implementation! { public new void MA() { ... } Programmering i C# - Kapitel 4
Gör implementationen virtuell interface IA { void MA(); } class A : IA { public virtual void MA() { ... } // virtuell här! class B : A { public override void MA() { ... } Programmering i C# - Kapitel 4
Standardinterface Interface standardiserar vanliga metoder eller grupper av metoder 19 standardinterface i biblioteket IDisposable med Dispose() ICloneable med Clone() IComparable med CompareTo() Programmering i C# - Kapitel 4
4.7 Arvet från Object Object är implicit basklass för alla typer Structer ärver indirekt via ValueType Har konstruktor – objekt kan skapas Sällsynta tillfällen Nio medlemmar varav tre är virtuella metoder som ofta omdefinieras ToString, GetHashCode och Equals Programmering i C# - Kapitel 4
Object public class Object { public Object() {...} ~Object() {...} public virtual string ToString() {...} public virtual int GetHashCode() {...} public virtual bool Equals(object obj) {...} public static bool Equals(object objA, object objB) {...} public static bool ReferenceEquals(object objA, object objB) {...} public Type GetType() {...} protected object MemberwiseClone() {...} } Programmering i C# - Kapitel 4
ToString Bör skapa sträng som beskriver objektet Medlemmars värden, eventuell ledtext Basklassversionen ger sträng med typnamnet Används av bl.a. Console.WriteLine Bra för spårutskrifter Kan vara användbart i användarinterface Programmering i C# - Kapitel 4
GetHashCode Bör returnera stort heltal beroende av objektets tillstånd Används av Hashtable Nödvändig om objekt ska läggas i Hashtable Hashtable kräver också omdefinierad Equals Basklassversionen returnerar referensens värde (minnesadress) – oanvändbar! Programmering i C# - Kapitel 4
Equals Två överlagrade: Virtuell instansmetod Statisk metod Instansmetoden bör omdefinieras då objekts tillstånd ska kunna jämföras Basklassversionen jämför referenserna Jämför alltså identitet, inte tillstånd Programmering i C# - Kapitel 4
Statiska Equals/ReferenceEquals Statiska Equals tar två object-referenser Kontrollerar om någon är null Kontrollerar om båda är lika Anropar annars instansmetoden Equals Statiska ReferenceEquals jämför alltid identitet Relevant om Equals omdefinierats Programmering i C# - Kapitel 4
Jämförelseoperatorerna Överlagring av == och != bör också ske om Equals omdefinierats Enkel implementation: anropa statiska Equals! public static bool operator==( MyClass objA, MyClass objB) { return Equals(objA, objB); } Programmering i C# - Kapitel 4
MemberwiseClone Omdefinieras inte Är en protected hjälpmetod för kopiering av objekt Kan användas för implementationen av ICloneable.Clone Ger ”shallow copy” – referenser kopieras Referenser bör tilldelas nytt objekt Programmering i C# - Kapitel 4