Avatar billede rmjdk Nybegynder
24. juli 2008 - 11:12 Der er 10 kommentarer

Interface arv

Jeg har et interface, ITestInterface, som definerer en metode, Execute() der returnerer ResultBase. Derudover har jeg et interface, IDerivedInterface, der arver fra ITestInterface, som gør Execute() mere specifik ved at benytte "new" foran metoden, og returnerer en klasse der arver fra ResultBase, nemlig DerivedResult.

I den specifikke klasse, DerivedClass, som implementerer IDerivedInterface vil den dog gerne have at jeg implementerer BÅDE Execute() fra ITestInterface samt IDerivedInterface, hvorimod jeg kun er interesset i Execute() metoden fra IDerivedInterface. Hvordan løses dette?

Se vedhæftede klassediagram.
http://peecee.dk/upload/view/124556
Avatar billede aaberg Nybegynder
24. juli 2008 - 11:51 #1
Du bliver nød til implementere begge metoder, ellers opfylder du ikke kriterierne specificeret af interfacet. Det du kan gøre er at implementere Execute metoden som returnerer en DerivedResult. Fra den anden Execute metode kalder du den første.

public class DerivedClass : IDerivedInterface
{
    public DerivedResult Execute()
    {
        //Kode her
    }

    BaseResult ITestInterface.Execute()
    {
        return ((IDerivedInterface)this).   
    }
}
Avatar billede aaberg Nybegynder
24. juli 2008 - 11:53 #2
Whoops, der forsvandt noget da jeg copy/pastede! Her er koden igen:

public class DerivedClass : IDerivedInterface
{
    public DerivedResult Execute()
    {
        //Kode her
    }

    BaseResult ITestInterface.Execute()
    {
        return ((IDerivedInterface)this).Execute();
    }
}
Avatar billede rmjdk Nybegynder
24. juli 2008 - 13:38 #3
Ja, det kom jeg også frem til, men synes ikke det er så pænt og forstå ikke helt logikken, da der netop i IDerivedInterface er specificeret end "new" Execute() metode.

Findes der alternative metoder til at kode dette "rigtigt" ?
Avatar billede aaberg Nybegynder
24. juli 2008 - 14:08 #4
Hvis du tænker lidt over det, er det logisk at du bliver nød til at implementere begge metoder. Du vil til en hver tid kunne putte en instans af IDerivedInterface ned i en variabel af typen ITestInterface, da den nedarver fra denne. En IDerivedInterface er også en ITestInterface, derfor skal den kunne opføre sig som en ITestInterface.

Hvis du har en variable af typen ITestInterface som indeholder en IDerivedInterface og du kalder Execute(), da vil kompileren forvente at der bliver returneret en BaseResult, hvor der i dette tilfælde vil blive returneret en DerivedResult. I dette eksempel ville det (Hvis det kunne lade sig gøre) gå godt, da DerivedResult nedarver fra BaseResult, men hvad hvis det havde være 2 helt forskellige returtyper?

Jeg vil mene at den måde du er i gang med at gøre det, er den rigtige. Når du opretter en instans af DerivedClass, vil det kun være den ene Execute() metode som er synlig. Hvis du har denne instans liggende i en variabel af typen ITestInterface, vil ITestInterface.Execute() metoden være synlig, men automatisk kalde den nedarvede klasses Execute metode.
Avatar billede arne_v Ekspert
24. juli 2008 - 14:55 #5
new betyder ny metode, saa er det vel ikke saa overraskende at den ikke betragtes
som vaerende den gamle.

Men jeg vil kraftigt anbefale dig at redesigne lidt. Det valgte design vil give
nogle meget tricky situationer.
Avatar billede arne_v Ekspert
24. juli 2008 - 15:09 #6
Proev of se paa dette eksempel:

using System;

namespace E
{
    public class DBase
    {
        public virtual void Test()
        {
            Console.WriteLine("I am a DBase");
        }
    }
    public class DDerived : DBase
    {
        public override void Test()
        {
            Console.WriteLine("I am a DDerived");
        }
    }
    public interface IBase
    {
        DBase GetD();
    }
    public interface IDerived : IBase
    {
        new DDerived GetD();
    }
    public class X : IBase, IDerived
    {
        DBase IBase.GetD()
        {
            return new DBase();
        }
        DDerived IDerived.GetD()
        {
            return new DDerived();
        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            IDerived o = new X();
            o.GetD().Test();
            IBase o2 = o;
            o2.GetD().Test();
            Console.ReadKey();
        }
    }
}

Det er meget ikke-polymorphistisk at GetD afhaenger af hvordan typen er erklaeret !
Avatar billede rmjdk Nybegynder
05. august 2008 - 11:13 #7
smider i et svar?
Avatar billede arne_v Ekspert
06. august 2008 - 02:05 #8
.
Avatar billede aaberg Nybegynder
13. august 2008 - 11:49 #9
svar :-)
Avatar billede aaberg Nybegynder
11. september 2008 - 11:49 #10
Du må huske at acceptere svarene!
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester