我目前有两个界面(我在这里命名为IA
和IB
):
interface IA {
int Width;
int Height;
...
}
interface IB {
int Width;
int Height;
...
}
共享相同的两个属性:它们都具有Width
和Height
属性。
我在考虑定义包含IMatrix
和Width
属性的Height
界面是否有任何意义:
interface IMatrix {
int Width;
int Height;
}
问题是虽然它们共享两个相同的属性,但我不会在我的任何编码中使用IMatrix
的多态性:即,在任何情况下我都不会想要使用IMatrix
,我只想使用IA
和IB
。添加IMatrix
似乎更像是过度工程而不是其他东西,但我想问你们你们对此事的看法。
由于
答案 0 :(得分:7)
如果您不会专门使用它,那么我会说您无需添加它。
答案 1 :(得分:6)
如果存在您正在使用或可能合理地希望将来使用的真实关系,那么抽象关系是有意义的。如果关系非常松散(它们恰好有两个属性意味着类似的东西,但在完全不同的上下文中),那么就没有理由提供抽象。
答案 2 :(得分:4)
我认为YAGNI原则适用。如果您不打算在代码中使用IMatrix
,那么您不需要它。您可以随时添加它,然后让IA
和IB
实施。你的其他代码(实现这两个接口的具体类)都不应该改变。
答案 3 :(得分:3)
如果您发现自己处于为IA
和IB
编写两个具有相同实现的方法的情况,那么通用接口是个好主意。否则,不需要通用接口。
如果您现在不处于这种情况,您必须评估将来发生的可能性,以及现在是否值得引入通用界面。
答案 4 :(得分:0)
这取决于意图,IMatrix如何发展以及代码的重点是什么。
例如,如果代码真的只关心维度,那么它可以使用IA / IB。但是如果调用代码专注于矩阵运算,那么创建这个子接口并使用它可能是有意义的。如果您以后添加特定于矩阵的属性或操作,例如GetCellValue或类似的,专门处理矩阵的代码所需,然后从一开始就使用IMatrix将使这更容易添加。如果你在真正关于矩阵的代码中使用IA / IB,那么你将不得不重构该代码以将IA / IB更改为IMatrix(可能涉及许多方法签名更改),或者在代码中从IA / IB进行向下转换需要IMatrix。
答案 5 :(得分:0)
公共接口可能有很多原因,IA和IB在其他区域可能有不同的属性和方法,但是如果它们都在某种程度上定义了Matrix,那么通用接口就会很棒。
作为一名伟大的程序员曾经说过:
如果可能的话简化一切 接口
我整理了一个解决方案,提供了一个最终可能会是什么样子的例子
class Program
{
static void Main(string[] args)
{
// D derives from C which implements interface IA and IB which
// are both derived from IMatrix
var matrix = new D {Height = 100, Width = 200};
// Method takes IMatrix
X(matrix);
// Method takes IA
Y(matrix);
// Method takes IB
Z(matrix);
// Method takes D
LastTest(matrix);
//
// Prints heights and widths 4 times
//
}
static void X(IMatrix x)
{
Console.WriteLine(string.Format("Height: {0}\r\nWidth: {1}\r\n\r\n",
x.Height, x.Width));
}
static void Y(IA x)
{
Console.WriteLine(string.Format("Height: {0}\r\nWidth: {1}\r\n\r\n",
x.Height, x.Width));
}
static void Z(IB x)
{
Console.WriteLine(string.Format("Height: {0}\r\nWidth: {1}\r\n\r\n",
x.Height, x.Width));
}
static void LastTest(D x)
{
Console.WriteLine(string.Format("Height: {0}\r\nWidth: {1}\r\n\r\n",
x.Height, x.Width));
}
}
internal interface IMatrix
{
int Width { get; set; }
int Height { get; set; }
}
internal interface IA : IMatrix
{}
internal interface IB : IMatrix
{}
internal class C : IA
{
public int Width { get; set; }
public int Height { get; set; }
}
internal class D : IA, IB
{
public int Width { get; set; }
public int Height { get; set; }
}
在某些情况下,您可能只需要宽度和高度,在其他情况下,您可能需要完整的IA或IB甚至实现(但应该简化为接口)。
但是,不要过度设计您的软件,考虑域并尝试提取常用部分。
有人可能会问为什么你会有你不使用的东西,IMatrix可能是一个“坏名字”但是你有另一个问题。 未使用代码=死代码,因此应予删除。
答案 6 :(得分:0)
另一个原则是不要重复自己(DRY),接口将在IA中“使用”,IB会扩展它,即使没有方法实际上采用IMatrix(或您决定的任何名称) )。
然而,在这种情况下重复很小,所以除非出现更多的共性(在接口方法或可以在IMatrix上运行的实用程序功能),否则它可能不会“概念性地承载它自身的重量”。
答案 7 :(得分:0)
在您的情况下,请不要设置IMatrix
界面。如果没有合同关系来证明它是合理的,那么接口没有任何意义。这就像先建一座桥,然后决定把它放在哪条河上。