Springen naar inhoud

Liskov in .net


  • Log in om te kunnen reageren

#1

Vladimir Lenin

    Vladimir Lenin


  • >250 berichten
  • 829 berichten
  • Ervaren gebruiker

Geplaatst op 09 juli 2009 - 21:56

Als ik volgende code schrijf
public interface ICloneable <T> : System.ICloneable {

   T Clone();

}

Krijg ik volgende error door de compiler:
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-- (Владимир Ильич Ульянов)

Dit forum kan gratis blijven vanwege banners als deze. Door te registeren zal de onderstaande banner overigens verdwijnen.

#2

Bart

    Bart


  • >5k berichten
  • 7224 berichten
  • VIP

Geplaatst op 09 juli 2009 - 22:13

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

#3

Vladimir Lenin

    Vladimir Lenin


  • >250 berichten
  • 829 berichten
  • Ervaren gebruiker

Geplaatst op 09 juli 2009 - 22:20

wat gaat hier dan verkeerd?
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-- (Владимир Ильич Ульянов)

#4

virtlink

    virtlink


  • >100 berichten
  • 158 berichten
  • Ervaren gebruiker

Geplaatst op 13 juli 2009 - 12:21

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:
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..."

#5

Vladimir Lenin

    Vladimir Lenin


  • >250 berichten
  • 829 berichten
  • Ervaren gebruiker

Geplaatst op 15 juli 2009 - 12:46

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:
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-- (Владимир Ильич Ульянов)





0 gebruiker(s) lezen dit onderwerp

0 leden, 0 bezoekers, 0 anonieme gebruikers

Ook adverteren op onze website? Lees hier meer!

Gesponsorde vacatures

Vacatures