C # -interfaces, polymorfisme en gedelegeerden

Ik heb een puinhoop als ik interfaces en polymorfisme combineer.

Stel dat ik de volgende interface heb:

public Interface CanSayHello
{
     String SayHello();
}

De volgende klasse:

public Class Person : CanSayHello
{
     public String SayHello() { return "Hey, I'm a person just saying hello to you";}
}

En tot slot de belangrijke klasse:

public Class PoshPerson: Person
{
     public String SayHello() { return "Hey, I'm too posh to say hello to you";}
}

Mijn eerste vraag is of de volgende code de methode van PoshClass of Person Class zou verzamelen?

public delegate String Collector();
event Collector CollectorEvent;
void GetMethod(CanSayHello c){CollectorEvent += c.SayHello;}

**GetMethod(new PoshPerson());**

Als het de methode uit de Person-klasse verzamelt, denk ik dat ik de methode bij Person als virtueel moet verklaren en de methode bij PoshPerson moet negeren. Ik zou echt willen dat de twee methodeshandtekeningen gelijk waren. Is het mogelijk op welke manier dan ook?

4
Welke van die zou je willen laten gebeuren? Als u wilt dat de implementatie in PoshPerson wordt aangeroepen, waarom wilt u dan voorkomen dat de methoden virtueel / negeren ? Persoonlijk zou ik vermijden dat de methode zich zoveel mogelijk zou verbergen, juist omdat compileertijd polymorfisme niet erg intuïtief is.
toegevoegd de auteur millimoose, de bron
Trouwens, de coderingsrichtlijnen zeggen dat je interfaces moet aangeven door een I als eerste letter te plaatsen.
toegevoegd de auteur Styxxy, de bron
toegevoegd de auteur Amittai Shapira, de bron
Moet het vrij gemakkelijk zijn om uit te zoeken wat er gebeurt?
toegevoegd de auteur Michael, de bron

3 antwoord

In uw voorbeeld wordt de methode Persoon uitgevoerd. Als u PoshPerson wijzigt in PoshPerson: Person, CanSayHello (waarvan u denkt dat deze niets zou veranderen, sinds Person: CanSayHello ), wordt uitgevoerd > PoshPerson 's methode.

Ik ben het eens met @millimoose: "Ik zou vermijden dat de methode zich zoveel mogelijk zou verbergen, juist omdat het compilatietijd polymorfisme niet erg intuïtief is." Ik zou aanraden dat u Person.SayHello in virtual en PoshPerson.SayHello in negeert . Op die manier, ongeacht of u het exemplaar kent als een CanSayHello , Persoon of PoshPerson , wordt de huidige methode van het exemplaartype uitgevoerd.

4
toegevoegd
De compiler geeft ook een waarschuwing af om het sleutelwoord new in de methodedeclaratie in PoshPerson te gebruiken als het verbergen in feite opzettelijk gebeurt.
toegevoegd de auteur Jeppe Stig Nielsen, de bron

Ik denk dat je meer wilt in de trant van:

public interface ITalkable
{ 
     string SayHello(); 
     string SayGoodbye();
     etc...
}

public class Person : ITalkable
{ 
     public virtual string SayHello() { return "Hey, I'm a person just saying hello to you";} 
     public virtual string SayGoodbye() { return "Hey, I'm a person just saying goodbye to you";}
} 

public class PoshPerson: Person 
{ 
     public override string SayHello() { return "Hey, I'm too posh to say hello to you";}
     public string MakePersonSayHello() { return base.SayHello(); } 

} 
1
toegevoegd

U voert bijvoorbeeld de versie van de persoon uit. Zie de uitleg hier: http://msdn.microsoft .com/nl-us/library/aa664593 (v = vs.71) .aspx . Als u de methode herdefinieert in een afgeleide klasse (de gecompileerde behandelt PoshPerson.SayHello alsof u nieuw hebt gebruikt om deze opnieuw te definiëren), en de basisklasse implementeert een interface, verandert de geherdefinieerde methode de interface-toewijzing niet.

Als u PoshPerson de interface opnieuw implementeert, wordt de SayHello van PoshPerson gebruikt.

public class PoshPerson : Person, CanSayHello
{
    public String SayHello() { return "Hey, I'm too posh to say hello to you";}
}

Of als u SayHello virtueel in persoon maakt en het vervolgens in PoshPerson opheft, wordt het de SayHello van PoshPerson genoemd.

1
toegevoegd
"Als PoshPerson de interface expliciet implementeert" is dat een beetje misleidend, omdat je het niet hebt over "expliciete interface-implementatie", maar over het opnieuw implementeren van de interface.
toegevoegd de auteur CodesInChaos, de bron
Goed punt @ CodeInChaos- bewerkt.
toegevoegd de auteur Japple, de bron