1 van 1

Liskov in .net

Geplaatst: do 09 jul 2009, 22:56
door Vladimir Lenin
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.

Re: Liskov in .net

Geplaatst: do 09 jul 2009, 23:13
door Bart
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.

Re: Liskov in .net

Geplaatst: do 09 jul 2009, 23:20
door Vladimir Lenin
wat gaat hier dan verkeerd?

Code: Selecteer alles

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



   T Clone();



}

Re: Liskov in .net

Geplaatst: ma 13 jul 2009, 13:21
door virtlink
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).

Re: Liskov in .net

Geplaatst: wo 15 jul 2009, 13:46
door Vladimir Lenin
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