【问题标题】:When to grow an interface, restrict it, or use implemetation to do so何时扩展接口、限制接口或使用实现来这样做
【发布时间】:2011-12-13 01:27:47
【问题描述】:

我经常难以确定何时扩大或缩小接口或使用某些实现来这样做。考虑一个矩阵;它可以是方形的,也可以不是方形的,所以我想说:

interface IMatrix<T>
{
  void InsertColumn(int position);
  void InsertRow(int position);
  void DeleteColumn(int position);
  void DeleteRow(int position);
  T ValueAt(int row, int col); //gets the value
  void ValueAt(int row, int col, T value); //sets the value
}

所以,上面的矩阵可以是正方形的,但它不一定是。我的第一个想法是使用一个类来创建方阵的想法

class SquareMatrix<T> : IMatrix<T>
{
   private IMatrix<T> matrix;
   public SquareMatrix(IMatrix<T> matrix) {this.matrix = matrix;}
   public void InsertColumn(int position)
   {
     // Must ensure that a row and column are both added to keep it square
     this.matrix.InsertRow(position);
     this.matrix.InsertColumn(position);
   }
   // rest of methods similarly perform a row and column operation to keep square...
 }
}

但是,我很快意识到我可以将方阵传递给构造函数并得到一些不好的结果,因为现在我将执行许多额外的操作。所以我觉得这不是一种将接口限制为正方形的好方法,除非有更好的方法来实现这个类。

然后我想,好吧...方阵比常规矩阵更具限制性,也许我应该从中提取一个接口...

interface ISquareMatrix<T>
{
  void InsertRow(int position);// adds a row and column, name selected for inheritance purposes
  void DeleteRow(int position);// deletes a row and column, ...
  void ValueAt(int row, int col, T value);
  T ValueAt(int row, int col);
}

interface IMatrix<T> : ISquareMatrix<T>
{
  void InsertColumn(int position);// adds only a column and now InsertRow should not also insert a column
  void DeleteColumn(int position);// deletes only a column
}

这看起来不错,但有点打破了我关于继承自 SquareMatrix IS-A Matrix 以来的思路,反之亦然。此外,由于我以一种使继承看起来不错的方式选择了我的名字,因此我对这种方法持谨慎态度。

abstract class MatrixBase<T> : IMatrix<T>
{
  //Base class simply provides a matrix that we can use
  IList<IList<T>> matrix = new List<IList<T>>();
  public MatrixBase(int rows, int columns)
  {
    if(rows < 1) {/*throw ...*/}
    if(columns < 1) {/*throw...*/}
    // add rows and columns
  }

  public abstract void InsertColumn(int position);
  // more abstract methods to implement interface
}
class Matrix<T> : MatrixBase<T>
{
  //override all methods so that insert column only inserts a column
  //and insert row only inserts a row
}
class SquareMatrix<T> : MatrixBase<T>//seems fishy since matrix base is an IMatrix
{
  //override all methods so that insert row inserts a row and column
  //and insert column calls insert row
}

如您所见,方阵恢复为矩阵,尽管接口会反向读取。

无论如何,这些都是我的想法;您将如何建模方阵和非方阵之间的关系? :) 谢谢!

【问题讨论】:

  • 为什么还要使用方阵呢?方阵只是两个维度具有相同大小的矩阵。你要给方阵类型一些不应该出现在非方阵上的特殊行为吗?
  • 方阵使一些事情更容易处理。例如,邻接矩阵总是方阵,我可以添加对矩阵进行幂运算的能力,因为乘法 AxA 只会在方阵上成功。
  • @Ani:太棒了,我想可能会有一些关于这个主题的研究。
  • 我知道方阵具有特殊属性,但利用这一点的方法应该存在于对象本身上,还是存在于利用它的算术引擎上?例如。我可以定义一个幂运算符,它可以将任何矩阵输入其中,但如果矩阵不是正方形,则会出错。

标签: c# generics inheritance interface base-class


【解决方案1】:

一般来说,接口应该只包含所有实现可以合理实现的方法。在这种情况下,我认为AddRowAddColumn 方法不应该是接口的一部分,而应该是Matrix 上的方法。

在 .NET 框架中,有一些接口示例过于宽泛并具有CanXxx 属性,因此您可以在调用方法之前检查方法是否对您拥有的特定对象有意义。所以我猜你也可以这样做,但我自己并不是它的忠实粉丝。

【讨论】:

  • 我不想让任何类公开,并且有一个返回 IMatrix 类型对象的工厂。这真的不应该在界面中吗?如果我取出添加和删除的行,那么只剩下 g/set 值。我觉得所有矩阵都应该能够添加行和列,只是方阵在添加时必须同时添加两者。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-07
相关资源
最近更新 更多