Interface
Interface är en datatyp och har alltså egen syntax och en hel del egna regler för vad arv från interface innebär. Interface är renodlad abstract klass och det enda som får deklareras i ett interface är metoder, egenskaper, indexer och events. I övrigt inga fält, konstruktorer, destruktorer, operatorer, konstanter, etc får deklareras i ett interface. Medlemmarna i ett interface har heller inga modifierare för synlighet, de är alltid public abstract. Interface innehåller ingen implementering av metoderna, metodkroppen ersätts med ett semikolon.
exempel interface IShape { void Move(int x, int y); double Area(); int X { get; set; } int Y { get; set; } } IShape Circle Class Circle : IShape { public void Move(int x, int y) { } public double Area() { return 0.0 } public int X { get { return x; } set { x = value; } } public int Y { get{ return y; } set{ y = value; } }
Interface Arv från interface är inte riktigt detsamma som arv från klasser. Mekanismen vid kompilering är annorlunda, det ska inte skapas någon basklassdel i objekten, inte anropas någon basklasskonstruktor, och lite annat. Därför benämna det inte arv utan kallar det implementation. En klass kan endast ärva från en basklass, men kan implementera ett valfritt antal interface (kommatecken mellan de). En struct kan inte ärva från någon klass alls, men kan implementera ett valfritt antal interface. Varje medlem i ett interface måste implementeras eller ärvas från en basklass. Interface används vid kompilering för att utföra en koll tillskillnad från arv där länkningen till lämpligt metod sker vid run-time.
Interface Metoder som finns i interface och som blir implementerade i klassen kan deklareras som: virtual anger första implementation av metoden abstact metoden har ingen implementation, men klassen blir abstrakt. Namnsättningen är smaksak, men stilen att namnet inleds med versalen "I" är mycket starkt förankrat, inte bara i C#. ”Vi ska eftersträva att följa konventionen”. C# skiljer inte på basklassen och interface mha nyckelord. C# använder sig istället av positionsnotation. Om en klass ärver från en annan klass och implementerar ett interface så skrivs först namnet på basklassen följt av ett komma följt av namnet på interface.
interface interface IA { ……. } class B { …… } class C : B, IA { ….. } ArvImplementaion
Interface När en klass implementerar ett interface, blir objekt av klassen också av interfacetypen. Om en klass implementerar två interface där medlemmar har samma namn, måste medlemmarna definieras explicit. Medlemmarna kan nu anropas endast via interfacereferens. interface IA { void SomeMethod(); } interface IB { void SomeMethod(); } class C : IB, IA { void IA.SomeMethod(){ ….. } void IB.SomeMethod(){ ….. } }
public interface IShape { void Move(int x, int y); double Area(); int X { get; } int Y { get; } } public class Circle : IShape { private int x; private int y; private int radius; public Circle(int x, int y, int radius) { this.x = x; this.y = y; this.radius = radius; } public int Radius { get { return radius; } set { radius = value; } } public int Y { get { return radius * 2; } } public int X { get { return radius * 2; } } public void Move(int x, int y) { this.x += x; this.y += y; } public double Area() { return System.Math.PI * radius * radius; } public class Rectangle : IShape { private int x; private int y; public Rectangle(int x, int y) { this.x = x; this.y = y; } public int Y { get { return y; } } public int X { get { return x; } } public void Move(int x, int y) { this.x += x; this.y += y; } public double Area() { return x * y; } public class MainApplication { public static void Main() { IShape[] ishapeLista = new IShape[2]; ishapeLista[0] = new Circle(5,5,10); ishapeLista[1] = new Rectangle(5, 3); foreach (IShape shape in ishapeLista) { Console.WriteLine( shape.Area().ToString()); }
Här är det enbart beteende som utgör den absoluta basklassen (interface), och implementationen kan bli helt annorlunda i olika sorters klasser. Att ha vissa fält i basklassen låser implementationen i härledda klasser i viss utsträckning. Med hjälp av interface har vi verkligen separerat beteende från tillstånd och implementation. När en klass implementerar flera interface måste naturligtvis alla medlemmar i alla interfacen implemeteras. Interface
Några råd om när det är lämpligt att använda interface Interface är lämpligt när det finns generella egenskaper i systemet som en klass kan välja att ha eller inte ha. Interface är tekniken att uppnå en form av multipelt arv, om en klass väljer att implementera ett flertal interface. Interface används när en klass skall kunna välja att en kombination av många mindre egenskaper. Varje egenskap uttrycks då i ett interface, och varje klass kan välja vilken kombination av egenskaper som är applicerbar på just den klassen. Råd
Tänk att man har skapat en instans av Circle klassen och undrar om klassen stödjer IShape beteende. Det finns 3 sätt att upptäcka det: ”type cast” när man vill att en referensvariabel pekar på ett objekt nedåt i arvhierarkin. Om en typomvandling med ”type cast” inte fungerar, händer ett körningsfel Man kan skaffa en interface från en objektreferens via nyckelordet "as". "as" syntax sätter interface-variabel till null om given interface inte stödjes av objektet än att kasta ett undantag. man kan skaffa en interface från ett objekt via en "is"-operator as, is, typeof
Circle c = new Circle(5,5,10); IShape sInterface; try { //kasta till en interface sInterface = (IShape)c; Console.WriteLine(sInterface.ToString()); } catch(InvalidCastException e) { Console.WriteLine("No IShape"); } Circle c = new Circle(5,5,10); IShape sInterface = c as IShape; if(sInterface != null) Console.WriteLine(sInterface.ToString()); else Console.WriteLine("No IShape"); Circle c = new Circle(5,5,10); if(c is IShape) Console.WriteLine(c.ToString()); else Console.WriteLine("No IShape");
Man kan inte skapa instanser av ett interface. Man får inte skapa några fält i ett interface. Man får inte ha några konstruktorer i ett inteface. Man får inte ha destruktorer i ett interface. Man kan inte nästla in några typer i ett interface. Man kan inte låta ärva från en struktur eller en klass. Repetition
När man implementerar ett interface, så måste man försäkra sig om att varje metod exakt överensstämmer med den motsvarande metoden i interfacet: Metoden måste vara uttryckligen deklarerad som public, eftersom interface metoder är definitionsmässigt publika. Retyrtyperna måste överrensstämma exakt. Metodnamnen måste vara exakt samma. Parametrarna måste stämma överens exakt. Om det finns några olikheter kommer kompileringen att misslyckas, eftersom interfacemetoden inte har implementerats. Repetition