Это развитие ответа Дэвида Калпа. Это довольно долго, поэтому я не публикую в качестве комментария.
Хотя общий интерфейс IList<TPoint>
выглядит хорошим решением, я бы порекомендовал немного проработать семантику. Кроме того, рекомендуется рассмотреть возможность использования как общих, так и неуниверсальных версий некоторых интерфейсов (например, IEnumerable
plus IEnumerable<T>
).
В вашем поясненном примере вы должны ввести термин, описывающий конечную сущность, которая имеет начальную и конечную точку. Обычно кривая - это не линия, а линия - это кривая. Однако, поскольку ваша кривая использует ControlPoint
s для описания ее начала и конца, в то время как линия вместо этого использует простые Point
s, в вашем конкретном случае линия не является кривой. Вместо этого и линия, и кривая представляют собой нечто вроде shape .
// this interface will denote any shape that has a starting and ending point
public interface IShape
{
IPoint Start { get; set; }
IPoint End { get; set; }
}
// this interface will allow for specialization of staring end ending points' type
public interface IShape<TPoint> : IShape
{
// note 'new' will be required here most probably, I didn't compile it
TPoint Start { get; set; }
TPoint End { get; set; }
}
// a line will be a shape descibed by a pair of points; for the sake of
public interface ILine : IShape<Point> { }
// a curve will be a shape described by a pair of control points
public interface ICurve : IShape<ControlPoint> { }
Тогда фактические реализации ILine
и ICurve
могут использовать явные реализации свойств Start
и End
, поступающие из неуниверсального интерфейса IShape
. Это будет способствовать строго типизированному доступу к точкам разграничения, сохраняя при этом возможность работать с ними, как с обычными IShape
с.
public class Curve : ICurve
{
public ControlPoint Start { get; set; }
public ControlPoint End { get; set; }
IShape.Start
{
get { return Start; }
set
{
if (!(value is ControlPoint)) ... some error handling ...;
Start = (ControlPoint)value;
}
}
IShape.End { ... similarly as IShape.Start ... }
}
public class Line : ILine { ... similarly as Curve ... }
Обратите внимание, что в отношении сценария возможной ошибки, показанного выше, улучшение может ограничивать свойства IShape
только для получателей. Или установщик, передающий value
в строго типизированную версию Start
или End
, может выполнить какое-то преобразование точки в контрольную точку. Разумеется, правильное решение зависит от конкретной области.