Cześć.
Mam pewną zagwozdkę. Zazwyczaj spotykałem się z potrzebą modelowania prostych struktur obiektowych, jednak teraz pojawiły się nieco bardziej skomplikowane modele i mam dwa sposoby, jak mogę je odzwierciedlić - zastanawiam, się który lepszy, co wy o nich sądzicie.
Mamy dwa interfejsy:
public interface IZwierzyniec<T>
{
void Glaszcz(T zwierze);
void Karm(T zwierze, Object karma);
}
public interface IStajnia<T>
{
void Siodłaj(T zwierze, Siodło siodło);
T WyprowadzZeStajni(T zwierze);
}
Szukając analogii - w każdym zwierzyńcu można pogłaskać zwierzę. W zasadzie w stajni, też można głaskać zwierzę. Mam teraz potrzebę zaimplementować stajnie która dostosowuje się do koni, kuców, osłów, oraz klatkę w której można przechowywać króliki, norki, nutrie, zatem implementuje:
public class Stajnia<T> : IStajnia<T>
{
public void Siodłaj(T zwierze, Siodło siodło)
{
throw new NotImplementedException();
}
...
}
public class Klatka<T> : IZwierzyniec<T>
{
void Glaszcz(T zwierze)
{
throw new NotImplementedException();
}
void Karm(T zwierze, Object karma)
{
throw new NotImplementedException();
}
...
}
Jednak w moim gospodarstwie agroturystycznym pojawia się potrzeba, żeby każde zwierzę można było pogłaskać czy nakarmić. Z drugiej strony trudno siodłać króliki czy nutrie, które przebywają w klatkach. Można zaimplementować zatem wiele interfejsów w przypadku stajni czyli:
public class Stajnia<T> : IStajnia<T>, IZwierzyniec<T>
{
public void Siodłaj(T zwierze, Siodło siodło)
{
throw new NotImplementedException();
}
void Glaszcz(T zwierze)
{
throw new NotImplementedException();
}
void Karm(T zwierze, Object karma)
{
throw new NotImplementedException();
}
}
Jednak od razu mi rzuca się obserwacja, że głaskać i karmić to będzie można zawsze, wiec czy nie lepiej zaproponować dziedziczoną hierarchię interfejsową i implementować pojedyncze interfejsy, albo bazowe, albo dziedziczone ? Podaje przykład który zastosuje dziedziczenie interfejsów, żeby osiągnąć co wyżej:
public interface IZwierzyniec<T>
{
void Glaszcz(T zwierze);
void Karm(T zwierze, Object karma);
}
public interface IStajnia<T> : IZwierzyniec<T>
{
void Siodłaj(T zwierze, Siodło siodło);
T WyprowadzZeStajni(T zwierze);
}
public class Klatka<T> : IZwierzyniec<T>
{
void Glaszcz(T zwierze)
{
throw new NotImplementedException();
}
void Karm(T zwierze, Object karma)
{
throw new NotImplementedException();
}
...
}
public class Stajnia<T> : IStajnia<T>
{
public void Siodłaj(T zwierze, Siodło siodło)
{
throw new NotImplementedException();
}
void Glaszcz(T zwierze)
{
throw new NotImplementedException();
}
void Karm(T zwierze, Object karma)
{
throw new NotImplementedException();
}
}
Ja osobiście jestem za rozwiązaniem 2. Moim zdaniem jest bardziej eleganckie, bardziej odzwierciedla rzeczywistość i sama konstrukcja interfejsu i dziedziczenia ogranicza programistę, który będzie zeń korzystał. Owszem, ciężko będzie zaimplementować np. stajnie gdzie nie można głaskać koni, ale taka jest filozofia mojego gospodarstwa, żeby zawsze sie dało. Co wy o tym sądzicie ? Widzicie jakieś inne zagrożenia poza zmniejszeniem elastyczności możliwości implementowania różnych interfejsów ?