Вот я делаю некий код для работы с кривыми.
Кривые могут быть разные - простые ломаные линии, квадратичные, кубические и т.д.
Хочу работать с ними единым образом, через интерфейсы точки и сегмента.
Но при этом хранить в сплайнах конкретные классы точек, чтобы обрабатывать их по разному.
Например поиск касательной к сплайну в случае простой линии на порядки проще и быстрее чем в сплайнах безье
Cобственно вопрос - можно-ли как-то обойтись без преобразований каждый раз интерфейса к конкретному классу и обратно?
Я тут начал читать про перезагрузку операторов преобразования: https://docs.microsoft.com/ru-ru/dotnet ... s/implicit
Но там вроде нельзя преобразовывать к интерфейсам.
Затем про ковариантность и контравариантность обобщенных интерфейсов: https://metanit.com/sharp/tutorial/3.27.php
И что-то прям вконец запутался )
То что я хочу вообще возможно?
Или это в принципе ошибочная архитектура и все такое?
Пока я вижу два решения:
1. Не хранить в сплайнах конкретные классы точек, а хранить их интерфейсы
Но тогда я лишаюсь возможности упрощать работу с точками внутри класса.
2. Преобразовать точки каждый раз.
Но это как-то тупо при большом количестве методов в интерфейсе сплайна.
Все чем будут отличаться эти методы - это тупо каст к конкретному классу.
Синтаксис:
Используется csharp
// Интерфейс точки
public interface IPoint
{
public Vector3 Position { get; set; } // Позиция
public Vector3 InHandle { get; set; } // Входная направляющая
public Vector3 OutHandle { get; set; } // Выходная направляющая
}
// Интерфейс сплайна
public interface ISpline
{
IEnumerable<IPoint> GetAllPoints(); // Получить все точки
void AddPoints(IEnumerable<IPoint> points); // Добавить точек
void RemovePoints(IEnumerable<IPoint> points); // Удалить точек
}
// ====================================
// Кривые безье
// Точка Безье
public class LinePoint : IPoint
{
public Vector3 Position { get; set; }
public Vector3 InHandle { get; set; }
public Vector3 OutHandle { get; set; }
}
// Кривая Безье
public class BezierSpline : ISpline
{
// Список точек безье
private readonly List<BezierPoint> Points = new List<BezierPoint>();
public IEnumerable<IPoint> GetAllPoints()
{
return Points; // Естественно не компилируется
return Points as IEnumerable<IPoint>; // Все хорошо
}
public void AddPoints(IEnumerable<IPoint> points)
{
// Работает, но нужно кастить
Points.AddRange(points as IEnumerable<BezierPoint>);
}
public void RemovePoints(IEnumerable<IPoint> points)
{
foreach (var point in points)
{
// Опять дурацкое преобразование к конкретному виду
Points.Remove(point as BezierPoint);
}
}
}
// ====================================
// Аналогичные классы для простой линии
// Точка линии
public class LinePoint : IPoint
{
// ...
}
// Сплайн линии
public class LineSpline : ISpline
{
// Список точек линии
private readonly List<LinePoint> Points = new List<LinePoint>();
// Аналогично классу BezierSpline
// ...
}