Комментарии 9
Как-то хотел применить такой подход: paste.org.ru/?x8y5qi — вот без компилятора, как вам кажется, всё окей?
var frame = new Frame()
.SetWidth(100)
.SetHeight(200)
.SetColor(Color.White);
А если появится наследник от Frame, то на SetColor(Color.White) все и закончится.
.SetWidth(100)
.SetHeight(200)
.SetColor(Color.White);
А если появится наследник от Frame, то на SetColor(Color.White) все и закончится.
А почему? Из-за проблем с ковариантностью и контравариантностью?
Вообще, это какая-то мудреная реализация. Не очень ясен ее исключительный профит.
Вообще, это какая-то мудреная реализация. Не очень ясен ее исключительный профит.
Вы очень внимательны! Я думаю это просто опечатка.
Чтобы делать наследника от Frame, сам Frame должен быть реализован соответственно тому же самому паттерну:
Ну и потом:
Как завещали наши прадеды в ATL 20 лет тому назад.
public class FrameImpl<Derived> : Rectangle<Derived>
{
Color _color;
public Derived SetColor(Color color)
{
_color = color;
return (Derived) this;
}
}
Ну и потом:
class Frame : FrameImpl<Frame>
{ /* здесь пусто, кроме может быть конструкторов */ };
Как завещали наши прадеды в ATL 20 лет тому назад.
Я такой способ применял для выноса в один из базовых классов методов, которые устарели. И макросом экранировал это наследование. Таким образом можно было собирать как с поддержкой обсолет\деприкейт, так и без нее. А сам класс оставался чистым.
Это сделано чтобы использовать GeoPointSerializer на манер хэлпера — через статические методы.
Можно написать так:
И использовать через создание объекта:
Можно написать так:
public abstract class SerializerBase<TSerializer, TItem> where TSerializer : SerializerBase<TSerializer, TItem>, new()
{
public abstract void WriteAsBinary(TItem item, BinaryWriter writer);
public void Save(TItem item, BinaryWriter writer)
{
WriteAsBinary(item, writer);
}
public void Save(IList<TItem> items, BinaryWriter writer)
{
writer.Write(items.Count);
foreach (var item in items)
WriteAsBinary(item, writer);
}
public void Save(string name, TItem item, BinaryWriter writer)
{
writer.Write(name);
WriteAsBinary(item, writer);
}
}
И использовать через создание объекта:
var gps = new GeoPointSerializer();
gps.Save("Mount Kilimanjaro", gp, writer);
gps.Save(region, writer);
При создании fluent интерфейсов с этот паттерн сам собой рождается)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Применение паттерна CRTP в C#