何时扩展接口、限制接口或使用实现来实现此目的
我经常难以确定何时扩展接口或缩小接口或使用某种实现来执行此操作。考虑一个矩阵;它可以是方形的,也可以不是方形的,所以我会说:
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矩阵,反之则不然。另外,由于我以一种让继承看起来不错的方式选择了我的名字,所以我对这种方法持谨慎态度。
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
}
正如您所看到的,方阵又恢复为矩阵,尽管接口会反向读取。
无论如何,这些是我的想法;您如何对方阵和非方阵之间的关系进行建模? :) 谢谢!
I often have trouble determining when to grow an interface or shrink it or use some implementation to do so. Consider a matrix; it can either be square or not, so I'd say:
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
}
So, the above Matrix could be square, but it does not have to be. My first idea was to use a class to create the idea of a square matrix as
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...
}
}
However, I quickly realized that I could pass a square matrix into the constructor and get some bad results as now I'll be doing many additional operations. So I feel like this is not a good approach for a way to restrict the interface to being only square unless there is a better way to implement this class.
So then I thought, well... square matrix is more restrictive than regular matrix, maybe I should extract an interface from that as...
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
}
This seems OK, but somewhat breaks my train of though pertaining to inheritance since a SquareMatrix IS-A Matrix, and not vice versa. Also, since I selected my names in a way that makes inheritance seem ok makes me cautious of this approach.
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
}
So as you can see, the square matrix is back to being a matrix though the interfaces would read in reverse.
Anyway, those are my thoughts; how would you model the relationship between a square matrix and a doesn't-have-to-be-square matrix? :) Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一般来说,接口应该只包含所有实现都可以合理实现的方法。在这种情况下,我认为
AddRow
和AddColumn
方法不应该是接口的一部分,而应该是Matrix
上的方法。在 .NET 框架中,有一些过于宽泛且具有 CanXxx 属性的接口示例,以便您可以在调用某个方法之前检查该方法对于您拥有的特定对象是否有意义。所以我想你也可以这样做,但我自己并不是很喜欢它。
Generally the interface should only include methods that all implementations can sensibly fulfill. In this case I think the
AddRow
andAddColumn
methods shouldn't be part of the interface but should instead be methods onMatrix
.In the .NET framework there are a few examples of interfaces that are overly broad and have
CanXxx
properties so that you can check whether or not a method makes sense for the specific object you have before calling it. So you could do this too I guess, but I'm not a big fan of it myself.