Det ser som oxo fint ud men hvis jeg så vælger at vil bruge et interface i den nye klasse hvordan skal det så se ud ?
interface MyNewInterface { bool myNewMethod }
class MyNewClass : ??? { public MyNewClass(){} //code away... }
Og sidst men ikke mindst har jeg så forstået det rigtigt at jeg så igennem den nye klasse kan trække alle metoder fra base klassen, noget i stil med dette :
Det er fuldstændig korrekt at du skal implementere alle metoder fra dit interface i din klasse eller kommer compileren med en fejl (derfor jeg skrev): :)
class MyNewClass : BaseClass, IClass { //Alle metoderne i IClass SKAL implementeres }
Men du behøver selvfølgelig ikke overskrive nogen af metoderne i BaseClass. :)
Ok jeg har leget lidt med det, så kome venligst med lidt kritik ;o)
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls;
namespace myNamespace1 { public interface iClass { string GetUser(); }
public class Class1 { private int _UserId; public int UserId { get { return _UserId; } set { _UserId = value; } }
private string _Firstname; public string Firstname { get { return _Firstname; } set { _Firstname = value; } }
private string _Lastname; public string Lastname { get { return _Lastname; } set { _Lastname = value; } }
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls;
namespace myNamespace2 { public class Class2 : myNamespace1.Class1, myNamespace1.iClass { // En masse ny kode her . . . } }
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using myNamespace2;
Du behøver ikke lave dem virtual, at lave dem virtual er dog en vigtig egenskab af polymorphismen og gør at hvis du kalder en metode i base-klassen er det den overskrevede metode i den nedarvede klasse der bliver kaldt, eksempel:
class BaseClass { public virtual string GetUser(); { return "Base"; } }
class Class1 : BaseClass { public override string GetUser() { return "Class1"; } }
BaseClass bs = new Class1(); Response.Write(bs.GetUser()); //Udskriver "Class1"
Dvs, hvis du kalder metoden fra BaseClass'en kalder den metoden fra Class1. Hvis du derimod ikke bruger 'virtual' kan du bruge 'new' til at overskrive en metode i base-klassen, forskellen er bare at hvis du kalder bs.GetUser() kalder den ikke metoden i Class1 men metoden i BaseClass, eksempel:
class BaseClass { public string GetUser(); { return "Base"; } }
class Class1 : BaseClass { public new string GetUser() { return "Class1"; } }
BaseClass bs = new Class1(); Response.Write(bs.GetUser()); //Udskriver "Base"
Du skal ikke gøre det til en vane at lave metoderne virtuelle... Det er en beslutning du tager fra metode til metode, og hvis du flager dem som override'able - skal du jo så også helst have sikret dig at det rent faktisk kan lade sig gøre, uden at funktionaliteten knækker.
Som snap skriver kan du godt redifinere en metode i en nedarvet klasse, men det er vanligvis lidt mere risikabelt, da du ikke nødvendigvis ved hvad du ender op med. Som du kan se af snaps eksempel - vil du kunne risikere at få kørt baseklassens metode i nogle tilfælde, og din egen implementering i andre. En fortsættelse af snaps eksempel:
Du har hentet et livssimulerings framework på nettet, og i det findes følgende klasse:
public class Human { public void Run() { // implementering af noget med at sætte den ene fod foran den anden.. // og tælle en distance op } }
I din egen applikatikation har du særlige behov, og har været nødt til at specialisere
public class HumanWithoutLegs : Human { public new void Run() { // lad være med at tælle en distance op // eller smid måske en exception. } }
Og frameworket giver dig mulighed for at sætte liv i dine personer:
// dit program Human h = new Human(); LifeEngine.StartModernLife(h);
Så starter personen et simuleret liv....
Metoden StartModernLife tager naturligvis et objekt af typen Human som parameter.
Det vil du så også gerne gøre med din egen person:
HumanWithoutLegs hh = new HumanWithoutLegs(); LifeEngine.StartModernLife(hh);
Hvilket går godt, fordi din egen type - HumanWithoutLegs - er en specialisering af Human.
Nu er det så sådan, at noget af det bemeldte simalator gør er følgende:
if(CurrentDay == Day.Sunday) { Gym gym = new Gym(); gym.ActivateHuman(h); // hvor h skal være af typen Human }
Gymnastiksalen gør så følgende
public class Gym { public void ActivateHuman(Human human) { human.Run(); } }
Hvilket vil have et temmelig uheldigt impact på din application - i og med at din person uden ben vil begynde at løbe...?!?
Hvis vi tager dit program igen (og forestiller os at du har redefineret Run med new: HumanWithoutLegs hh = new HumanWithoutLegs(); LifeEngine.StartModernLife(hh);
Og ændrer det sådan her: HumanWithoutLegs hh = new HumanWithoutLegs(); hh.Run(); LifeEngine.StartModernLife(hh);
Så vil dit eget kald til hh.Run() gøre som den skal, men det kald frameworket udfører efterfølgende vil gøre noget aldeles ulogisk - nemlig at lade personen gå. Det samme objekt vil altså opføre sig forskelligt rundt omkring i din applikation.
Den slags applikationer er ikke rare at have med at gøre.
Havde du gjort som følger: public class Human { public virtual void Run() { // implementering af noget med at sætte den ene fod foran den anden.. } }
public class HumanWithoutLegs : Human { public override void Run() { // lad være med at tælle en distance op // eller smid måske en exception. } }
Ville du have fået din egen implementering.
Ganske kort kan det siges, at den virtuelle metode medfører at den faktiske metode først bliver slået op på kørselstidspunktet, hvorimod den ikke-virtuelle slås op på kompileringstidspunktet.
I det tilfælde hvor Run() ikke er vituel vil det her: public class Gym { public void ActivateHuman(Human human) { human.Run(); } }
Medføre at kompileren kan slå Human-klassens implementering af Run op (og måske endda inline den, hvis den finder det mest optimalt), og på den måde får du aldrig kørt din egen implementering.
Det er et tænkt eksempel, men er du med på risikoen?
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.