Gebruikersavatar
Vladimir Lenin
Artikelen: 0
Berichten: 829
Lid geworden op: do 25 sep 2008, 14:15

Liskov in .net

Als ik volgende code schrijf

Code: Selecteer alles

public interface ICloneable <T> : System.ICloneable {



   T Clone();



}


Krijg ik volgende error door de compiler:

Code: Selecteer alles

warning CS0108: ICloneable<T>.Clone() Hides inherited member System.ICloneable.Clone(). Use the new keyword if hiding was intended.
Maar eigenlijk wil ik de methode niet verbergen.

Volgens het Liskov principe mag je retourneertype enger zijn van een overgeerfde methode dan van de Generalisatie. Override gaat niet, wat doe ik verkeerd. indien ik hide, bestaat de methode van ICloneable simpelweg niet meer op ICloneable<T> gebied.
"Als je niet leeft zoals je denkt, zul je snel gaan denken zoals je leeft."

--Vladimir Lenin-- (Владимир Ильич Ульянов)
Gebruikersavatar
Bart
Artikelen: 0
Berichten: 7.224
Lid geworden op: wo 06 okt 2004, 22:42

Re: Liskov in .net

T kan van alles zijn, terwijl System.ICloneable een object als retourneertype verwacht. Als T een double is, dan mag je het Liskov principe niet toepassen.
If I have seen further it is by standing on the shoulders of giants.-- Isaac Newton
Gebruikersavatar
Vladimir Lenin
Artikelen: 0
Berichten: 829
Lid geworden op: do 25 sep 2008, 14:15

Re: Liskov in .net

wat gaat hier dan verkeerd?

Code: Selecteer alles

public interface ICloneable<T> : System.ICloneable where T : object {



   T Clone();



}
"Als je niet leeft zoals je denkt, zul je snel gaan denken zoals je leeft."

--Vladimir Lenin-- (Владимир Ильич Ульянов)
virtlink
Artikelen: 0
Berichten: 158
Lid geworden op: di 21 mar 2006, 18:44

Re: Liskov in .net

Bij werken met generics mag je de regels zoals je die kent met overerving niet toepassen. Dus T Clone() is een andere methode dan object Clone(), maar hebben behalve de naam en het aantal parameters niets gemeen.

Microsoft gebruikt dit principe ook voor sommige interfaces, zoals ICollection. Daarbij zijn er ook methodes met dezelfde naam maar een verschillend signatuur. Wat ze dan doen, vertaald naar jouw probleem, is:

Code: Selecteer alles

public interface ICloneable<T>

{

T Clone();

}

public class MyClass : ICloneable<MyClass>, ICloneable

{

public MyClass Clone()

{

// ...

}

public object ICloneable.Clone()

{

return Clone();

}

}
(Code is niet getest.)

Dus één klasse implementeert beide interfaces, maar de eis dat je ICloneable moet implementeren als je ICloneable<T> implementeert, is weggelaten (net als dat het .Net library geen "ICollection<T> : ICollection" interface definieert). Om toch voor beide interfaces een implementatie te geven (dat is tenslotte verplicht als je erft van beide) gebruik je voor de 'oude' methode(s) de naam van de interface ervoor. Dit principe zorgt ervoor dat je in IntelliSense alleen jouw generic Clone methode ziet, maar je het object kan casten naar een ICloneable (niet generic) en Clone dan ook werkt (maar dan de niet generic versie die een object terug geeft).
"Niet gehinderd door enige kennis van zaken..."
Gebruikersavatar
Vladimir Lenin
Artikelen: 0
Berichten: 829
Lid geworden op: do 25 sep 2008, 14:15

Re: Liskov in .net

Dat had ik idd al door, toch vind ik het vreemd dat je geen constraints aan je generic kunt meegeven zodat je Liskov kunt toepassen. k'heb al gezocht maar hij verwerpt alles wat ik probeer zoals:

Code: Selecteer alles

1. where T : object

2. where T : System.Object

3. where T : class
"Als je niet leeft zoals je denkt, zul je snel gaan denken zoals je leeft."

--Vladimir Lenin-- (Владимир Ильич Ульянов)

Terug naar “Informatica en programmeren”