[C#] Vraag over interfaces

Pagina: 1
Acties:

  • Jabbah
  • Registratie: Februari 2004
  • Laatst online: 26-05 20:20
Niet echt een probleem maar meer een theoretische vraag:

Stel je hebt een interface IStorable:
code:
1
2
3
4
5
interface IStorable
{
    void Read();
    void Write();
}

Nu kan je op 2 manieren bv de Read() methode aanroepen:
code:
1
2
MyClass myClass = new MyClass();
myClass.Read();

OF
code:
1
2
3
4
5
6
MyClass myClass = new MyClass();
IStorable isStorable = (IStorable)myClass;
if (isStorable != null) // myClass implementeert inderdaad de IStorable interface
{
    isStorable.Read()
}

Je kan dus rechtstreeks op een instantie van de class de Read methode aanroepen of via de interface referentie.

De tweede manier (dus via de interface) zou de beste manier moeten zijn vanwege polymorfisme.

Dat laatste begrijp ik niet. Wie kan dat nader uitleggen? Thanks.

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 22:24

gorgi_19

Kruimeltjes zijn weer op :9

Als je via de interface aanroept, zit je niet vast aan de achterliggende class. Anders is het volstrekt nutteloos in dit voorbeeld om uberhaupt die interface te implementeren.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • whoami
  • Registratie: December 2000
  • Laatst online: 21:56
Weet je wat polymorphisme is? Zonee, dan moet je daar eens eea over lezen.

Zoja, dan zou je het eigenlijk zowiezo moeten snappen.

Stel, je hebt 2 classes die de IStorable interface implementeren: Class1 en Class2.
Stel dat je dan een collectie hebt van objecten die allemaal de IStorable interface implementeren, en dat je voor ieder object de Print() method moet gaan uitvoeren.
Dan doe je gewoon:
code:
1
((IStorable)myArray[i]).Print()

En de juiste Print() implementatie zal voor ieder object aangeroepen worden.

Als je een reference naar een object die de IStorable interface implementeert bijhoudt, dan moet je ook nooit weten welke concrete class dat is:

code:
1
IStorable myObj = new Class1()

https://fgheysels.github.io/


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Interfaces is het mechanisme om multiple-type inheritance te implementeren. Dit is een van de 2 aspecten van multiple inheritance. (de andere is multiple implementation inheritance, dat is niet gesupport door .NET natively (wel in Eiffel.NET)).

Dus je kunt je class meerdere types geven dmv een interface implementatie. Zodoende kun je meerdere class typen met dezelfde logica laten werken, die bv werkt op objects met de interface IFoo (dus het type 'IFoo' zijn).

IStorable is een prima kandidaat voor multiple inheritance en het nut van MI te illustreren aangezien het puur behaviour georienteerd is. In .NET zul je echter elke keer de IStorable implementatie zelf moeten uitvoeren, voor elk type dat je storable wilt maken.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Overigens denk ik dat dit:
IStorable isStorable = (IStorable)myClass;
if (isStorable != null) // myClass implementeert inderdaad de IStorable interface

een specified cast not valid exception geeft in het geval dat myClass geen IStorable implementeert. Gebruik het C# statement 'as':

IStorable isStorable = myClass as IStorable;
if (isStorable != null) // myClass implementeert inderdaad de IStorable interface

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 26-05 23:14
Even voor de goede orde: als je een MyClass object hebt, dan heeft het natuurlijk geen enkele zin om 'm naar een IStorable object te gaan casten. De suggesties van EfBe zijn wat mij betreft dus allebei fout.

Waar het echter wel om gaat is dat het voor de algemeenheid (en daarmee de bruikbaarheid) van je code belangrijk is om niet om een specifieker type te vragen dan je nodig hebt. Een functie die alleen maar de Read en Write members gebruikt om een bepaalde algemene functie uit te voeren, zal dus een IStorable argument krijgen. Je kunt die functie dan immers met MyClass objecten aanroepen maar ook met andere objecten die weliswaar niet van type MyClass zijn, maar wel IStorable implementeren.

whoami's tweede voorbeeld geeft trouwens ook een typische situatie aan, waarin een type wel bestaat om algemeen gedrag te definiëren maar niet geïnstantieerd kan worden (omdat het een interface of een abstract class is). In sommige gevallen kan het nuttig zijn om een object van MyClass te instantiëren en dat toe te kennen aan een variabele met type IStorable, als je zeker weet dat je niet het specifieke gedrag van MyClass nodig hebt. Op beperkte schaal (binnen een functie, bijvoorbeeld) vind ik dit zelf echter niet zo nodig.

[ Voor 3% gewijzigd door Soultaker op 19-03-2004 16:04 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 21:56
EfBe schreef op 19 maart 2004 @ 15:33:
Interfaces is het mechanisme om multiple-type inheritance te implementeren. Dit is een van de 2 aspecten van multiple inheritance. (de andere is multiple implementation inheritance, dat is niet gesupport door .NET natively (wel in Eiffel.NET)).
Mjah, dat is niet echt een antwoord op de specifieke vraag van de TS.
Dus je kunt je class meerdere types geven dmv een interface implementatie. Zodoende kun je meerdere class typen met dezelfde logica laten werken, die bv werkt op objects met de interface IFoo (dus het type 'IFoo' zijn).

IStorable is een prima kandidaat voor multiple inheritance en het nut van MI te illustreren aangezien het puur behaviour georienteerd is. In .NET zul je echter elke keer de IStorable implementatie zelf moeten uitvoeren, voor elk type dat je storable wilt maken.
Het is idd een manier om multiple inheritance te implementeren, maar ik heb eigenlijk nog vrijwel nooit een class van meer dan 1 class moeten inheriten.
Een interface zorgt voor een contract waar je class zich moet aan houden, en dat je een base class of interface kunt gebruiken als 'container' voor een concreet type en dat je dan die 'container' kunt aanspreken zonder dat je hoeft te weten van welk concreet type het object nu precies is. Dat is imo één van de belangrijkste features van inheritance.

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 21:56
EfBe schreef op 19 maart 2004 @ 15:35:
Overigens denk ik dat dit:
IStorable isStorable = (IStorable)myClass;
if (isStorable != null) // myClass implementeert inderdaad de IStorable interface

een specified cast not valid exception geeft in het geval dat myClass geen IStorable implementeert. Gebruik het C# statement 'as':

IStorable isStorable = myClass as IStorable;
if (isStorable != null) // myClass implementeert inderdaad de IStorable interface
Ik denk dat deze constructie nog beter is:

code:
1
if( myClass is IStorable )

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 21:56
Soultaker schreef op 19 maart 2004 @ 15:50:
Even voor de goede orde: als je een MyClass object hebt, dan heeft het natuurlijk geen enkele zin om 'm naar een IStorable object te gaan casten. De suggesties van EfBe zijn wat mij betreft dus allebei fout, net als het eerste voorbeeld van whoami.
Mijn eerste code voorbeeld is wel juist, omdat ik ervan uitging dat de collection een arraylist. Als je een item van een arraylist haalt, dan krijg je een object terug van het type 'object' (ook al zijn het eigenlijk objecten van het type Class1 of Class2).
Dus, dat object moet je zowiezo eerst nog casten naar de IStorable interface voor je een IStorable method wilt aanspreken.

https://fgheysels.github.io/


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 22:24

gorgi_19

Kruimeltjes zijn weer op :9

Waar het echter wel om gaat is dat het voor de algemeenheid (en daarmee de bruikbaarheid) van je code belangrijk is om niet om een specifieker type te vragen dan je nodig hebt.
Dit ben ik ook niet helemaal met je eens. Door middel van een interface kan je ook bepaalde methods of properties beschikbaar maken welke je anders niet of moeilijk kan benaderen. neem een visitor of een observer als voorbeeld.

Het lijkt mij niet een alleen een probleem van specifiekere types.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 26-05 23:14
whoami schreef op 19 maart 2004 @ 15:54:
Mijn eerste code voorbeeld is wel juist, omdat ik ervan uitging dat de collection een arraylist. Als je een item van een arraylist haalt, dan krijg je een object terug van het type 'object' (ook al zijn het eigenlijk objecten van het type Class1 of Class2). Dus, dat object moet je zowiezo eerst nog casten naar de IStorable interface voor je een IStorable method wilt aanspreken.
Ah, ok, ik dacht dat je een MyClass object naar een algemener type (IStorable) ging casten. Beetje verwarrend voorbeeld, in deze context, omdat de cast naar IStorable niet zoveel met het probleem (of het polymorfisme dat je beschrijft) van doen heeft, maar het voorbeeld klopt dan inderdaad wel.
gorgi_19 schreef op 19 maart 2004 @ 16:00:
Dit ben ik ook niet helemaal met je eens. Door middel van een interface kan je ook bepaalde methods of properties beschikbaar maken welke je anders niet of moeilijk kan benaderen. neem een visitor of een observer als voorbeeld.

Het lijkt mij niet een alleen een probleem van specifiekere types.
Dit volg ik niet helemaal. Kun je het uitleggen of misschien een kort voorbeeld geven van wat je bedoeld?

[ Voor 28% gewijzigd door Soultaker op 19-03-2004 16:04 ]


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 22:24

gorgi_19

Kruimeltjes zijn weer op :9

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Public Interface IKostenPerMaand

    ReadOnly Property Bedrag() As Double

End Interface

Public Class Huis
    Inherits BaseHouseClass
    Implements IKostenPerMaand

    Public ReadOnly Property Bedrag() As Double Implements IKostenPerMaand.Bedrag
        Get
            Return 10000
        End Get
    End Property

End Class

Public Class Verzekeringskosten
    Inherits BaseInsuranceClass
    Implements IKostenPerMaand

    Public ReadOnly Property Bedrag() As Double Implements IKostenPerMaand.Bedrag
        Get
            Return 5000
        End Get
    End Property
End Class

Hierboven even heel snel een beetje ranzig voorbeeld in elkaar gezet, maar geeft wel een idee. Stel ik zet bovenstaande in een array. Door alles te casten naar IKostenPerMaand kan je alles in 1 keer doen. Je kan niet aan om naar een generieker type te casten, aangezien dat er niet is.

Door middel van een eigen Interface voorkom je het probleem.

[ Voor 4% gewijzigd door gorgi_19 op 19-03-2004 16:19 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • whoami
  • Registratie: December 2000
  • Laatst online: 21:56
:?
Ik snap het niet zo hoor gorgi_19. Je cast toch naar een generieker type, nl. IKostenPerMaand ?

https://fgheysels.github.io/


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 22:24

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 19 maart 2004 @ 16:20:
:?
Ik snap het niet zo hoor gorgi_19. Je cast toch naar een generieker type, nl. IKostenPerMaand ?
Hmmmm.. Ben ik weer eens naampjes door elkaar aan het halen? :P

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • Jabbah
  • Registratie: Februari 2004
  • Laatst online: 26-05 20:20
whoami schreef op 19 maart 2004 @ 15:51:
[...]


Ik denk dat deze constructie nog beter is:

code:
1
if( myClass is IStorable )
Heb me nog even wat verder in verdiept. The 'is' operator is wat minder efficient dan de 'as' operator. Als je naar de MSIL code kijkt, dan zie je dan bij de 'is' operator de interface check 2 keer wordt uitgevoerd; bij het if-statement en de cast. De 'as' operator voert de check maar 1 keer uit.

Als je wil checken of een object een bepaalde interface implementeert en je wil dit object direct casten, dan kan je het beste de 'as' operator gebruiken. In het geval dat je alleen op de interface wil checken en pas op een later moment de cast uitvoeren, kan je beter de 'is' operator gebruiken.

  • whoami
  • Registratie: December 2000
  • Laatst online: 21:56
As returned null als de conversie niet gelukt is. Dat wil dus zeggen dat je, nadat je gecast hebt, ook nog eens op null moet checken.

https://fgheysels.github.io/


  • EfBe
  • Registratie: Januari 2000
  • Niet online
checken op null is stukken goedkoper dan nog eens een cast uitvoeren :)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com

Pagina: 1