[c#/2.0]Interfaces en sub-classes

Pagina: 1
Acties:

Onderwerpen


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Topicstarter
Ik ben een applicatie aan het maken en nou kwam ik het volgende tegen met betrekking tot interfaces.

Ik heb een interface IModuleInstance en die heeft een Property Module van het type IModule

nou ben ik een implementatie van IModuleInstance aan het maken ModuleInstance en die heeft natuurlijk ook de Property Module. Alleen weet ik natuurlijk welke implementatie van IModule ik daar terug geef ( Module ). Nou vindt de compiler dat ik dat type daar niet aan mag geven omdat mijn signature dan niet overeenkomt. Op zich is dat wel logisch. Maar waarom is het eigenlijk zo dat ik daar niet een specifieker type aan mag geven. Op die manier voldoe ik toch eigenlijk nog gewoon aan de interface.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
interface IModuleInterface
{
    IModule Module{ get; }
}

interface IModule{} 

class Module : IModule {}

class ModuleInterface : IModuleInterface
{
    Module Module //Dit mag dus niet 
    {
        get{ return module; }
    }
}

Op zich is het makkelijk op te lossen door gewoon als return type IModule te hebben of eventueel een expliciet de interface IModuleInterface te implementeren. Ik vroeg me echter af waarom dit niet gewoon goed gerekend wordt.

Bij delegates is het tenslotte ook mogenlijk op de volgende manier

C#:
1
2
3
4
5
6
7
8
delegate void MyEventHandler( object sender, MySpecificEventArgs e );
event MyEventHandler MyEvent;

public void MyMethod( object sender, EventArgs e )
{
}

MyEvent += MyMethod;


Het haalt voor MyMethod natuurlijk niet uit dat hij een specifieker type van EventArgs krijgt. Zo lijkt het mij ook in mijn voorgaande voorbeeld dat een eventuele gebruiker van IModuleInterface niet interesant dat er een specifieker type van IModule terug wordt gegeven.

Mijn vraag is dus: Waarom is er voor gekozen om dit te verbieden?

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
Het is toch logisch dat dat niet mag, en ik vind het juist dat het verboden wordt ook.

Stel dat je implementatie van IModule (Module dus), een aantal specifieke properties / methods heeft, die niet gedefinieerd zijn in de interface IModule.

Als jouw constructie zou toegelaten worden, dan zou je in principe dit kunnen doen:
code:
1
MyModuleInstance.Module.TheSpecificMethod();

Hoe kan je compiler trouwens checken of je altijd een instance van Module returned, en geen andere implementatie van IModule ? Wat als je daar een factory gebruikt bv die ergens in een config file gaat kijken en adhv die waarde bepaalt wat er moet teruggegeven worden ?

Het zou me trouwens ook verbazen dat het met die method wel mag... Omgekeerd, dat zou ik begrijpen. (Dus je delegate die EventArgs specifieert, en je method zelf die MySpecificEventArgs als parameter heeft (als MySpecificEventArgs dus inherit van EventArgs).

Hetgeen jij wil doen, zou je echter wel met generics kunnen oplossen, denk ik...
code:
1
2
3
4
interface IModuleInterface<T> where T : IModule
{
    T Module {get;}
}


code:
1
2
3
4
5
6
7
8
9
10
class ModuleInterface : IModuleInterface<T> where T : IModule
{
    T Module
    {
        get
        {
             return new T();
        }
    }
}

Zoiets; (niet getest ofzo...)

[ Voor 4% gewijzigd door whoami op 16-11-2006 17:35 ]

https://fgheysels.github.io/


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Topicstarter
Ja met generics kan je het "Oplossen". Het is ook niet echt een probleem hoor maar ik vindt het vreemd.

De compiler kan in mijn implementatie tenslotte zien dat ik altijd een Module terug geef
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class ModuleInstance : IModuleInstance
{
    private Module module;

    public Module Module
    {
        get { return (Module)((IModuleInterface)this).Module; }
    }
    public IModule IModuleInstance.Module
    {
        get{ return module; }
    }
}

Op deze manier mag het wel. Je geeft dezelfde klass terug. Hetgene wat ik bedoel is dat de interface verwacht dat je een Property hebt die Module heet een een IModule terug geeft. Als je implementatie dan een Property heeft die Module heet en een Module terug geeft voldoe je daar toch eigenlijk ook aan aangezien een Module IModule implementeerd.

Je zou het dan gewoon zo kunnen gebruiken.
C#:
1
2
3
4
5
6
7
8
9
10
IModuleInstance instance = new ModuleInstance();
IModule module = instance.Module;

//of
ModuleInstance instance = new ModuleInstance();
Module module = instance.Module;

//Dit mag dan natuurlijk niet
IModuleInstance instance = new ModuleInstance();
Module module = instance.Module;//Kan een IModule niet assignen aan een Module

Zolang je dan als type een IModuleInstance hebt zal het return type IModule zijn maar als je als type ModuleInstance hebt dan weet je als gebruiker dat je een specifieker type terug krijgt. Ik kan niet echt een situatie bedenken wanneer het problemen oplevert.

offtopic:
ik heb overigens een beetje onhandige namen voor de voorbeeld classes gebruikt maar dat terzijde

[ Voor 9% gewijzigd door Woy op 16-11-2006 19:13 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Paul
  • Registratie: September 2000
  • Laatst online: 20:09
Even tussendoor :P Gaat de compiler niet zeuren dat je nu een naam herbruikt? Module <> Module, welke bedoel je dan? De class, of de instantie?

In theorie kun je wel onderscheid maken door te kijken of je een static method/member opvraagt of een gewone, maar een instantie van Module Module noemen lijkt me sowieso al ranzig :P

"Your life is yours alone. Rise up and live it." - Richard Rahl
Rhàshan - Aditu Sunlock


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Topicstarter
Paul Nieuwkamp schreef op vrijdag 17 november 2006 @ 00:29:
Even tussendoor :P Gaat de compiler niet zeuren dat je nu een naam herbruikt? Module <> Module, welke bedoel je dan? De class, of de instantie?

In theorie kun je wel onderscheid maken door te kijken of je een static method/member opvraagt of een gewone, maar een instantie van Module Module noemen lijkt me sowieso al ranzig :P
Zie mijn offtopic wijziging ;). Het mag overigens wel.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”