Я пишу код в библиотеке C#, чтобы сделать clustering на (двумерный) набор данных - по существу разбивая данные на группы или кластеры. Чтобы быть полезной, библиотека должна принимать «общие» или «пользовательские» данные, класть ее и возвращать кластерные данные.Передача и возврат пользовательских данных - являются ли интерфейсы правильным подходом?
Для этого мне нужно предположить, что каждый элемент данных в передаваемом наборе данных имеет связанный с ним двумерный вектор (в моем случае Lat
, Lng
- я работаю с координатами).
Моя первая мысль была использовать общие типы, и проходят в двух списках, один список общих данных (т.е. List<T>
), а другой такой же длины, с указанием 2D векторов (т.е. List<Coordinate>
, где Coordinate
это мой класс для определения пара lat, lng), где списки соответствуют друг другу по индексу. Но это довольно утомительно, потому что это означает, что в алгоритме я должен как-то отслеживать эти индексы.
Моя следующая мысль была использовать inferfaces, где я определить интерфейс
public interface IPoint
{
double Lat { get; set; }
double Lng { get; set; }
}
и убедитесь, что данные, которые я прохожу в реализует этот интерфейс (то есть я могу предположить, что каждый элемент данных передается в имеет Lat
и a Lng
).
Но для меня это тоже не работает. Я использую свою библиотеку C# для остановки кластеров в транзитной сети (в другом проекте). Класс называется Stop
, и этот класс также из внешней библиотеки, поэтому я не могу реализовать интерфейс для этого класса.
То, что я тогда был унаследован от Stop
, создавая класс под названием ClusterableStop
который выглядит следующим образом:
public class ClusterableStop : GTFS.Entities.Stop, IPoint
{
public ClusterableStop(Stop stop)
{
Id = stop.Id;
Code = stop.Code;
Name = stop.Name;
Description = stop.Description;
Latitude = stop.Latitude;
Longitude = stop.Longitude;
Zone = stop.Zone;
Url = stop.Url;
LocationType = stop.LocationType;
ParentStation = stop.ParentStation;
Timezone = stop.Timezone;
WheelchairBoarding = stop.WheelchairBoarding;
}
public double Lat
{
get
{
return this.Latitude;
}
}
public double Lng
{
get
{
return this.Longitude;
}
}
}
, который, как вы можете видеть, реализующий интерфейс IPoint
. Теперь я использую конструктор для ClusterableStop
, чтобы сначала преобразовать все Stop
s в наборе данных в ClusterableStop
s, затем запустить алгоритм и получить результат как ClusterableStop
s.
Это не совсем то, что я хочу, потому что я хочу сделать что-то на Stop
с основан на том, что кластерные они падают. Я не могу этого сделать, потому что я на самом деле экземпляр новых остановки, а именно ClusterableStop
с!
Я все еще могу получить то, что хочу, потому что, например, Я могу восстановить исходные объекты по идентификатору. Но, конечно, есть намного более элегантный способ выполнить все это? Правильно ли это использовать интерфейсы? Казалось, что такая простая идея - переход и возврат пользовательских данных - но оказалось настолько сложным.