Jag är rätt ny med interfaces så kanske jjag tänker fel här.. Kanske inte ger var på din fråga, men jag fick lite information om interfaces som du kan titta igenom och se när man t ex kan använda det osv. Foreach opererar på IList eller IList of T men Roger då! :) ..nån version av IEnumerable räcker fint. Tack för svaren, men jag tror jag börjae i fel ända. Så glöm det jag skrev förut och svara på det här istället så kanske jag får någon uppfattning över hur det fungerar. :) Vad skall din IItemList ha för funktionalitet som inte IEnumerable<IItem> skulle ha? >>nån version av IEnumerable räcker fint. IItemList har en del metoder för att "ladda" listan med items. Du behöver inte göra Item klassen generisk Tack för det långa svaret CCecilia, det gjorde det mycket klarare! Jag hade inte lagt GetRelatedItems(); på Movie utan haft en tjänst/service (domänservice) som hade gjort detta för att koppla. dvs Tack för all hjälp! Nu löste jag det såhär:Behöver lite interface-hjälp
Jag har en klass:
<code>
public class ItemList : List<Item>, IItemList
//med interfacet:
public interface IItemList
</code>
Sen har jag en metod:
<code>
public Boolean LoadReleatedTo(IItemList items, int amount, int start)
{
foreach (Item item in items)
{
HttpContext.Current.Response.Write(item.Name);
}
}
</code>
Men det här fungerar inte eftersom interfacet IItemList "does not contain a public definition for 'GetEnumerator'".
Så hur löser jag det här? Kan man ha ett interface som ärver från ett annat?
Jag vill inte att parametern "items" ska vara av typen ItemList eftersom jag (om jag förstått det rätt?) då inte kan skicka in ett objekt som ärver ifrån ItemList, t.ex. "CarItemList". Eller kan man göra en cast, t.ex. LoadReleatedTo((ItemList) CarItemListInstans, 5, 0)?
Och till sist, ska man använda interface som parametrar på det sätt jag gjort eller är det dumt på något sätt?Sv: Behöver lite interface-hjälp
http://www.pellesoft.se/communicate/forum/view.aspx?msgid=272012&forumid=44&sum=1Sv: Behöver lite interface-hjälp
Så för att kunna göra det du vill så måste din IItemList ärva IList < Item > (eller snarare utöka då det är ett interface)Sv:Behöver lite interface-hjälp
förslagsvis kan du göra så att IItemList ärver IEnumerable<Item>Sv: Behöver lite interface-hjälp
Jag har 2 klasser:
Item : IItem
ItemList : List<Item>, IItemList
Låt oss nu säga att jag skapar 2 andra klasser som extendar dessa
Movie : Item
MovieList : ItemList
Nu har jag 2 problem
1. MovieList är fortfarande en lista med Items och inte filmer.
2. Movie klassen har en del metoder som returnerar ItemList, men dom ska ju returneras som MovieLists.
Borde jag göra Item och ItemList till generiska kontroller?Sv:Behöver lite interface-hjälp
Sv: Behöver lite interface-hjälp
Jo självklart, men eftersom han ärvde List<T> så antog jag att han var ute efter hela featuresettet.
men sure, det är osant att foreach opererar på ilist bara :-)
Faktum är att det inte ens kräver IEnumerable..
http://blogs.msdn.com/kcwalina/archive/2007/07/18/DuckNotation.aspx
C# kompilatorn kör med ducktyping vid foreach och kollar om klassen man foreachar över har en GetEnumerator metod, oavsett om klassen implementerar IEnumerable eller inte.Sv:Behöver lite interface-hjälp
<code>
public interface IItemList
{
Boolean LoadReleatedTo(Item item, int amount);
Boolean LoadReleatedTo(ItemList items, int amount, int start);
}
</code>Sv: Behöver lite interface-hjälp
public class Item : IItem
{
private string _name;
public string name
{
get {return _name;}
set { _name = value; }
}
}
public interface IItem
{
string name { get; set; }
}
eftersom du vill kunna göra foreach på nåt som du hantera som interfacet IItemList behöver den ha interfacet IEnumerable (arv fungerar även på interface). IEnumerable kräver en Datatyp så vi ger den en variabel sådan men vi säger att den måste vara en implementation av IItem. Det är dumt att använda ItemList klassen i interfacet använd Interfacen istället, de blir mera generella då.
public interface IItemList<T> : IEnumerable<T>
where T : IItem
{
Boolean LoadReleatedTo(IItem item, int amount);
Boolean LoadReleatedTo(IItemList<T> items, int amount, int start);
}
Nu till själva listklassen. När vi väljer att implementerar IItemList behöver vi också skriva funktionerna som finns i IEnumerable eftersom IItemList nu även innehåller det interfacet. Men Vi gör det lätt för oss, dessa funktioner är skrivna i List klassen och när vi ärver från den får vi dessa implementationer gratis. Vi lägger en Generic på listklassen för att kunna ha funktioner som returnerar Item eller MovieItem. Vi passar på att säga att den generiska data typen bara får vara av en IItem typ samt att den måste innehålla en default konstruktor (en new utan argument) så vi kan göra new på en T typ. returnList är en exempelfunktion som returnerar en lista med Item eller MovieItem.
public class ItemList<T> : List<T>, IItemList<T>
where T : IItem, new()
{
public ItemList<T> returnList()
{
ItemList<T> returnValue = new ItemList<T>();
T newItem = new T();
newItem.name = "test";
returnValue.Add(newItem);
return returnValue;
}
}
Nu kan du skriva ärvande klasser som fungerar som du tänkt dig
public class MovieList : ItemList<MovieItem>
{
}
public class MovieItem : Item
{
}
Skall listan inte ha någon ny funktionallitet bara för att den innehåller filmer istället för Items så kan du nu använda ItemList klassen men för filmer
public class MovieItem : Item
{
}
...
ItemList<MovieItem> l = new ItemList<MovieItem>();
...
Sv:Behöver lite interface-hjälp
Vad jag fortfarande inte har greppat är:
Låt oss säga att jag i min Item-klass har metoden:
<code>
public ItemList<Item> getReleatedItems()
{
ItemList<Item> il = new ItemList<Item>();
il.LoadReleatedTo(this.Id);
return il;
}
</code>
Det här borde ju fungera bra så länge man jobbar med basklassen. Det skulle då användas såhär:
<code>
Item i = new Item();
i.Load(5);
ItemList<Item> il = i.getReleatedItems();
</code>
Men hur fungerar det här med extendade klasser?
Movie : Item
MovieList : ItemList<Movie>
Nu vill jag att Item-metoden getReleatedItems() ska returnera en MovieList och inte en ItemList<Item>. Måste jag skriva om metoden i Movie-klassen såhär?:
<code>
public MovieList getReleatedItems()
{
MovieList il = new MovieList();
il.LoadReleatedTo(this.Id);
return il;
}
</code>
Nu medan jag skrev började det klarna lite och jag antar att den korrekta vägen är att om-definiera metoden i Movie-klassen, har jag rätt?Sv: Behöver lite interface-hjälp
<code>
IEnumerable<Movie> MovieService.GetRelatedMovies(Movie movie);
</code>Sv:Behöver lite interface-hjälp
Jag skapade en ny klass:
<code>
public abstract class Tools<I,IL>
where I : IItem, new()
where IL : IItemList<I>, IList<I>, new()
</code>
Här har jag metoderna
<code>
public static IL GetReleatedTo(IL items, int amount, int start)
public static IL GetReleatedTo(I item, int amount, int start)
</code>
m. fl.
Item-klassen är nu otroligt mycket förenklad och innehåller bara load och en del properties.
Movie-klassen extendar Item-klassen och det är där jag kallar på metoderna i Tools-klassen.
MovieList extendar ItemList<Movie>
Jag har också en Toolbox-klass som extendar Tools<Item, ItemList>, mest av lättja för att slippa skriva typerna varje gång men även för att kunna lägga till funktioner ifall det behövs. Tanken är att koden i Tools aldrig ska behöva röras såvida man inte sätter in någon basfunktionalitet för alla item-typer.
Var det en bra lösning? Kan det göras bättre?
Nu känner jag åtminstone att jag börjar ha lite koll på det här. :)