2012-04-22 2 views
0

У меня есть общий класс Vector<T> и общий класс Matrix<T>, и мне было интересно, было бы неплохо, чтобы оба класса реализовали интерфейс.Интерфейс для классов Vector и Matrix?

В принципе, я реализация два алгоритма: AlgorithmA и AlgorithmB, оба из которых выполняют очень похожие операции (сброс, средний ... и т.д.), но с различными алгоритмами и действуют на различные структуры: AlgorithmA использует Vector<double> в то время как использование AlgorithmBMatrix<Complex>.

Конструкция у меня до сих пор:

abstract class AlgorithmArray 
{ 
    // Operator overloading 
} 

class AlgorithmAArray : AlgorithmArray 
{ 
    private Vector<double> _vector; 

    // Overrides 
} 

class AlgorithmBArray : AlgorithmArray 
{ 
    private Matrix<Complex> _matrix; 

    // Overrides 
} 

Я предпочел бы иметь AlgorithmAArray проистекают из Vector<T>, а также реализовать интерфейс «IAlgorithmArray» (вместо абстрактного класса). Во всяком случае, эти алгоритмы затем используются для моделирования передачи/приема между двумя точками:

public class CommunicationParameters 
{ 
     private AlgorithmArray _transmission; 
     private AlgorithmArray _receiving; 

     public void Compute() 
     { 
      if(_transmission != null) 
       _transmission.Compute(); 

      if(_receiving != null)   
       _receiving.Compute() 

     } 
} 

Существуют ли более эффективные способы приблизиться к моей проблеме?

Примечание: базовый класс AlgorithmArray дублирует многие методы оператора/клонирования ... и т. Д., И я чувствую, что этого можно избежать, возможно, используя дженерики?

Спасибо!

ответ

1

Я бы предложил сделать два класса алгоритмов, которые могут принимать любую структуру данных в качестве параметра и выполнять свою задачу. Я не вижу необходимости в этом наследовании ООП, это просто добавляет сложности.

1

Интерфейсы позволят выполнять процедуры, которые только считывают или только записывают векторы/матрицы для принятия векторов/матриц подтипа или супертипа ожидаемого типа вектор/матрица. Я не уверен, что это было бы полезно с матрицами, но это могло бы быть удобно с некоторыми приложениями векторов.

Другим преимуществом интерфейсов над классами, которые могут быть более применимы к вашей ситуации, было бы то, что они могли бы обеспечить плавное взаимодействие между изменяемыми, неизменяемыми и объектами копирования на запись (последнее требует дополнительного уровня косвенности) , Это может быть полезно, если у вас много векторов или матриц, которые будут копиями друг друга, но некоторые из них в конечном итоге будут изменены. Для этого могут быть полезны методы AsImmutable, AsNewMutable и AsPossiblyExistingMutable. Первый метод (если он вызывается на изменяемом объекте) будет либо создавать новый неизменяемый объект, содержимое которого совпадает с содержимым его объекта во время вызова, либо (если оно вызвано на неизменяемом) объекте, просто возвращает его объект. Второй будет создавать новый изменяемый объект независимо от того, является ли существующий объект изменчивым или неизменным. Третий метод будет возвращать объект, если он изменен, или создать новый изменяемый объект; его обычно следует использовать только в тех случаях, когда владелец объекта знал бы, что если объект изменчив, он содержит единственную ссылку.

Например, если у меня есть частное поле _thing типа IReadableVector<Foo>, мой сеттер может установить его value.AsImmutable() и мой добытчик может вернуться _thing.AsImmutable(). Мой метод мутации установил _thing = _thing.AsPossiblyExistingMutable(), прежде чем вызывать методы мутации. Если я не пытался мутировать _thing, так как я получил его, это был бы неизменный объект (к которому другие объекты могли бы также содержать ссылки). В первый раз, когда я его мутирую, он будет скопирован на новый изменяемый объект. Однако последующие мутации могут продолжать использовать один и тот же изменяемый объект, поскольку он никогда не будет подвергаться воздействию какого-либо внешнего кода.

PS - Есть аргументы за и против, имеющие IImmutableVector<T> и IImmutableMatrix<T> как интерфейсы, по сравнению с только имея ImmutableVector<T> и ImmutableMatrix<T> классов. С одной стороны, если они являются интерфейсами, возможно иметь полезные реализации, которым не нужно фактически хранить все элементы. Например, можно было бы иметь такие классы, как AllMatchingVector<T>, который наследует IImmutableVector<T>, но содержит только один номер T и номер, обозначающий его длину; его индексированный геттер просто вернет этот элемент независимо от указанного индекса или DiagonalMatrix<T>, который просто содержит IImmutableVector<T> для содержимого своей диагонали и T, который будет возвращен везде; особенно для больших векторов/матриц, такие классы могут сэкономить память. С другой стороны, не было бы способа гарантировать, что никто не реализовал один из этих интерфейсов с классом, который на самом деле не был неизменным. Мое личное чувство заключается в том, что для этого хорошо использовать интерфейсы. В конце концов, мало кто жалуется, что SortedDictionary<T> потерпит неудачу, если класс реализует IComparable<T> таким образом, который не дает неизменного отношения сортировки. Тем не менее, многие люди не согласны с такой концепцией.

Смежные вопросы