Grundkurs i C-Sharp - Överlastning
Förord
Om du inte redan gjort det, så kommer du med största sannolikhet att göra det någon gång under din tid som programmerare. Det jag talar om är en teknik som kallas för överlastning [1]. Det innebär att man kan ha flera metoder eller attribut med samma namn i samma klass fast med olika innebörd.Innehåll
»»
»
»
»
»
»
Relaterade artiklar
» Grundkurs i C-Sharp - Arv» Grundkurs i C-Sharp - Gränssnitt
» Grundkurs i C-Sharp - Introduktion
» Grundkurs i C-Sharp - Namnrymder
» Grundkurs i C-Sharp - Polymorphism
» Grundkurs i C-Sharp - Statiska medlemmar
» Grundkurs i C-Sharp - Strukturer
» Grundkurs i C-Sharp - Undantagshantering
» Grundkurs i C-Sharp - Åtkomstmodifiering
Metoder
För den ovana kanske detta låter konstigt och för att snabbt och enkelt komma underfull med en möjlig situation där överlastning behövs så ber jag dig att tänka på klassen Math som jag skapade i min artikel om statiska medlemmar.
class Math
{
public static int Add(int a, int b)
{
return a+b;
}
public static int Multiply(int a, int b)
{
return a*b;
}
public static int Substract(int a, int b)
{
return a-b;
}
}
Denna klassen kan enbart hantera heltal och detta kanske är tillräckligt i många situationer men vad skulle hända om du skulle behöva utföra denna typen av operationer på t.ex. decimaltal? För den person som inte är bekant med överlastning kanske lösningen skulle se ut på följande sätt.
class Math
{
public static int Add(int a, int b)
{
return a+b;
}
public static int Multiply(int a, int b)
{
return a*b;
}
public static int Substract(int a, int b)
{
return a-b;
}
}
Här har vi skapat en uppsättning matematiska operationer för heltal (namn givna med Int i slutet) och en uppsättning för decimaltal (namngivna med Double i slutet). Detta är förvisso en helt acceptabel lösning men ack så dynamisk, då den kräver att man redan i förväg vet vilken typ av tal som man behöver utföra en beräkning på.
Vi kommer snart att se hur samma klass skulle se ut med hjälp av överlastning, men först ska vi gå igenom ett par regler som man måste följa för att kunna ha flera olika metoder eller attribut med samma namn i samma klass. Det säger sig själv att metoderna och attributen inte kan vara helt identiska, utan vad det måste skilja sig på är någon av följande
- 1. Parameter typen
- 2. Antalet parametrar
Det är alltså inte möjligt att genomföra överlastning genom att endast skilja på
- 1. Parameternamnen
- 2. Retur värdet
- 3. Att använda sig av ByRef eller ByVal i någon av parametrarna
Hur skulle då vår Math klass se ut om vi skrev om den med hjälp av överlastning? Betrakta följande program kod för att se resultatet av omskrivningen.
class Math
{
public static double Add(double a, double b)
{
return a+b;
}
public static int Add(int a, int b)
{
return a+b;
}
public static double Multiply(double a, double b)
{
return a*b;
}
public static int Multiply(int a, int b)
{
return a*b;
}
public static double Substract(double a, double b)
{
return a-b;
}
public static int Substract(int a, int b)
{
return a-b;
}
}
Lägg märket till att det finns två metoder av varje sort med samma namn, skillnaden är att de skiljer sig på de parametrar som man skickar in och i detta fall skiljer sig retur värdet också men det är inget som har med överlastning att göra, eftersom enbart olika returvärden kvalificerar sig som en överlastning (som jag tidigare nämnde).
Det råkar också vara så att I detta fallet är det så att den kod som uppgör de olika överlastade metoderna är helt identisk, men detta är inte ett måste utan koden inne i de olika överlastade metoderna kan vara helt olika.
För att avsluta stycket om metoder tar vi oss en snabb titt på hur man skulle använda metoderna i vår nya Math klass.
double a = 3.5;
double b = 1.5;
double c = Math.Add(a, b); // c innehåller nu 5.0
int d = 7;
int e = 2;
int f = Math.Add(d, e); // f innehåller nu 7
Lägg märket till att det finns två metoder av varje sort med samma namn, skillnaden är att de skiljer sig på de parametrar som man skickar in och i detta fall skiljer sig retur värdet också men det är inget som har med överlastning att göra, eftersom enbart olika returvärden kvalificerar sig som en överlastning (som jag tidigare nämnde).
Det råkar också vara så att I detta fallet är det så att den kod som uppgör de olika överlastade metoderna är helt identisk, men detta är inte ett måste utan koden inne i de olika överlastade metoderna kan vara helt olika.
För att avsluta stycket om metoder tar vi oss en snabb titt på hur man skulle använda metoderna i vår nya Math klass.
double a = 3.5;
double b = 1.5;
double c = Math.Add(a, b); // c innehåller nu 5.0
int d = 7;
int e = 2;
int f = Math.Add(d, e); // f innehåller nu 7
Attribut
Det är exakt samma regler som gäller när man skall utnyttja överlasting på attribut istället för metoder. Då likheterna är så stora tänker jag inte behandla attribut med ett långt exempel utan nedan ser du ett exempel på en klass som har ett överlastat attribut.
class OutputManager
{
FileStream s;
string FileName
public string Source
{
get { return FileName; }
set { FileName = value; }
}
public FileStream Source
{
get { return s; }
set { s = value; }
}
}
Konstruktor
Den observanta läsaren som även läst min översikts artikel om klasser kanske har lagt märket till att det även är möjligt att använda överlastning konstruktorer i en klass. Precis som med metoder och attribut måste sig antalet parametrar eller parameter typerna skilja sig för att det skall vara en giltig överlastning.
Standardvärde och valbara parametrar
För dem av er som kommer från en bakgrund i Visual Basic så är kanske standardvärde (default values) och valbara (optional) parametrar något som ni använt er av när ni skrev metoder. I C-Sharp finns inte dessa tekniker utan man använder sig helt enkelt av överlastning för att uppnå samma sak.För att illustrera hut man skapar valbara parametrar med överlastning så kan vi skapa en klass Debug som innehåller en metod som heter Error och som skall kunna ta emot en sträng med beskrivningen av felet och ha en valbar parameter som avgör om felet skall skrivas in i loggfilen eller inte.
class Debug
{
public void Error(string Message)
{
// Hantera felet
}
public void Error(string Message, bool WriteToLog)
{
// Hantera felet
if ( WriteToLog == true )
// skriv till logfilen.
}
}
Nu kan man använda Error metoden och antingen skicka med parametern WriteToLog eller inte.
Debug d = new Debug();
d.Error(”Ett fel uppstod”); // Skriver inte till loggen
d.Error(”Kunde inte läsa filen”, false); // Skriver inte till loggen
d.Error(”Det finns inget ledig minne”, true); // Skriver till loggen
Som du ser innehåller båda överlastningarna av metoden Error kod för att hantera felet och det kan tyckas vara dumt att ha samma kod på två ställe. Detta kan vi lösa genom att använda ett standardvärde. Vi bestämmer oss för att om man använder den korta formen av Error med bara en parameter så skall den inte skriva till loggen. Vi kan då anropa den långa formen av Error ifrån en korta och skicka med ett standardvärde på false till WriteToLog parametern.
class Debug
{
public void Error(string Message)
{
this.Error(Message, false);
}
public void Error(string Message, bool WriteToLog)
{
// Hantera felet
if ( WriteToLog == true )
// skriv till logfilen.
}
}
Nu behöver vi bara skriva koden för att hantera felet på ett ställe och fortfarande få vårt program att fungera på exakt det sättet som vi vill.
Staffan sjöstedt
Tjena Andreas, Kul med alla dina artiklar här på Pellesoft Kodexemplet ( nummer 2) där klassen skulle ha varit med double i st för int har fortfarande int som typer. Hälsn /Handleiter Xtaffan class Math { public static int Add(int a, int b) { return a+b; } ......